DataFormatter關(guān)于CPU消耗測試

POCT日歷頁面初始化的階段在iPhone6上帝雇,會(huì)有明顯的卡頓情況,通過Instrument查看谱煤,發(fā)現(xiàn)耗時(shí)最長的是第三方控件FSCalendar摊求,因?yàn)镕SCalendar里面的內(nèi)容未開放源碼處理,所以暫時(shí)無法對(duì)其進(jìn)行修改。

在查看了代碼后室叉,發(fā)現(xiàn)日歷頁面有大量關(guān)于時(shí)間格式轉(zhuǎn)換相關(guān)的內(nèi)容睹栖,而使用DateFormatter會(huì)消耗大量的CPU,使用緩存的方式將DateFormatter對(duì)象進(jìn)行緩存會(huì)在一定程度上提高效率茧痕。下面通過使用緩存和未使用緩存野来,通過CPU的消耗進(jìn)行對(duì)比,更直觀的了解緩存DateFormatter對(duì)象可以提高CPU工作效率踪旷,減少時(shí)間曼氛。未使用緩存相關(guān)的代碼

// 未使用緩存

func yyyyMMddDate() -> Date?{

????let formatter = DateFormatter()

????formatter.dateFormat = "yyyy-MM-dd"

????print("yyyy-MM-dd")

????return formatter.date(from: self) }

????// 使用緩存

????func yyyyMMddDateTest() -> Date?{

????????let thread = Thread.current.threadDictionary

????????if thread.object(forKey: "cacheFormatterData") != nil {

????????????let f: DateFormatter = thread.object(forKey: "cacheFormatterData") as! DateFormatter

?????????????return f.date(from: self)

????????} else {

????????????let f = DateFormatter()

????????????f.dateFormat = "yyyy/MM/dd"

????????????thread.setObject(f, forKey: "cacheFormatterData" as NSCopying) return f.date(from: self) ? ? ? ? ? ? ? ? ? ?

}

}

通過這兩個(gè)方法同樣點(diǎn)擊10次得到的CPU消耗情況如下圖所示:

左邊10個(gè)表示未緩存時(shí)的CPU消耗,右邊是緩存了DataFormatter對(duì)象所引起的CPU消耗令野,很明顯做了緩存的比未做緩存減少了大量的CPU消耗舀患。所以緩存DataFormatter對(duì)象這個(gè)方案可以用到日歷頁面中。接下來我們可能會(huì)有新的疑問:因?yàn)槭裁丛蚴咕彺鍰ateFormatter對(duì)象CPU的消耗明顯減少气破?

- 創(chuàng)建DateFormatter對(duì)象聊浅?

- 使用DateFormatter對(duì)象的屬性或方法?為了驗(yàn)證上面提出的問題现使,修改了代碼低匙,重新進(jìn)行測試:

?func yyyyMMddDate() -> Date? {

????????let formatter = DateFormatter()

????????formatter.dateFormat = "yyyy/MM/dd"

????????return formatter.date(from: self)

????}

????// 使用情況 func yyyyMMddDateTest() -> Date? {

????????let h = DateFormatter()

????????return Date()

}

同樣重復(fù)之前的驗(yàn)證操作,得到的結(jié)果如下圖所示:

看樣子創(chuàng)建DataFormatter對(duì)象并不是引起CPU大量消耗的原因碳锈,是不是意味著顽冶,如果我們在緩存的對(duì)象中使用了對(duì)象的屬性或者方法,所產(chǎn)生的CPU消耗和未緩存的應(yīng)該是一致的售碳。

帶著這樣一個(gè)疑問强重,我們再對(duì)代碼進(jìn)行修改:

```func yyyyMMddDate() -> Date? {

????????let formatter = DateFormatter()

????????formatter.dateFormat = "yyyy/MM/dd"

????????return formatter.date(from: self)

????}

????// 使用情況

????func yyyyMMddDateTest() -> Date? {

????????let thread = Thread.current.threadDictionary

????????if thread.object(forKey: "cacheFormatterData") != nil {

????????????let f: DateFormatter = thread.object(forKey: "cacheFormatterData") as! DateFormatter

????????????f.dateFormat = "yyyy/MM/dd" return f.date(from: self)

? ? ? ? ?} else {

????????let f = DateFormatter()

????????f.dateFormat = "yyyy/MM/dd"

????????thread.setObject(f, forKey: "cacheFormatterData" as NSCopying)

????????return f.date(from: self)

????}

}

重復(fù)之前的驗(yàn)證操作,得到的結(jié)果如下圖所示:


通過這個(gè)對(duì)比贸人,感覺非常奇怪竿屹,明明做了相同的操作,但是使用了緩存的還是明顯的比未使用緩存的CPU的消耗更小灸姊,這到底是為什么拱燃?出于對(duì)這個(gè)問題存在極大困惑,仔細(xì)看了看跟threadDictionary相關(guān)的內(nèi)容力惯,爭取從這些內(nèi)容里面找出使什么操作減少了CPU消耗碗誉。

>蘋果的官方文檔對(duì)threadDictionary的描述

You can use the returned dictionary to store thread-specific data. The thread dictionary is not used during any manipulations of the NSThread object—it is simply a place where you can store any interesting data. For example, Foundation uses it to store the thread’s default NSConnection and NSAssertionHandler instances. You may define your own keys for the dictionary.

主要的意思就是threadDictionary只是可以存儲(chǔ)任何數(shù)據(jù)的地方。

看來threadDictionary的這個(gè)猜想也不成立父晶。

再回過來看dateFormat的定義

>@property (null_resettable, copy) NSString *dateFormat;

因?yàn)檎{(diào)用DateFormat對(duì)象的dateFormat屬性哮缺,而這個(gè)屬性會(huì)進(jìn)行copy操作,而估計(jì)緩存在thread中的DateFormat對(duì)象已經(jīng)進(jìn)行了copy甲喝,所以不用在設(shè)置dateFormat屬性時(shí)進(jìn)行copy的操作尝苇。從而減少了CPU的消耗。

那么是否所有的緩存都會(huì)減少消耗呢?

我們使用POCT的NEUserDefault進(jìn)行相同的緩存操作糠溜,具體的代碼實(shí)現(xiàn)如下圖所示:

?func yyyyMMddDate() -> Date? {? ? ?

????? let formatter = DateFormatter()? ?

? ? ? formatter.dateFormat = "yyyy/MM/dd"? ? ?

????? return formatter.date(from: self)?

? }? ? ?

? // 使用情況? ? func yyyyMMddDateTest() -> Date? {? ?

? ? if NEUserDefaults.init().object(forKey: "cacheFormatterData") != nil {? ? ?

? ? ? let f: DateFormatter = NEUserDefaults.init().object(forKey: "cacheFormatterData") as! DateFormatter? ? ? ?

? ? return f.date(from: self)? ?

? ? } else {? ? ? ? ?

????????? let f = DateFormatter()? ? ?

????? ? ? f.dateFormat = "yyyy/MM/dd"? ? ? ?

? ? ? ? ? NEUserDefaults.init().setObject(f, forKey: "cacheFormatterData")? ? ?

????? ? ? return f.date(from: self)? ?

? ? ? ?} ? ?

?}

根據(jù)同樣的操作我們得到以下的結(jié)果:

看到這個(gè)圖的時(shí)候淳玩,是比較詫異的,做了緩存和沒做緩存的非竿,居然做了緩存的消耗的CPU更高蜕着。而這個(gè)更加明確了使用

thread.current.threadDictionary進(jìn)行DataFormatter對(duì)象的緩存具有優(yōu)勢。

以后會(huì)探索thread.current.threadDictionary的存儲(chǔ)內(nèi)容的原理對(duì)比使用NeUserDefault使用緩存的優(yōu)缺點(diǎn)红柱。

tips:在上面的測試實(shí)踐中承匣,發(fā)現(xiàn)print方法也會(huì)明顯的消耗CPU的使用。在開發(fā)過程中锤悄,發(fā)布版本應(yīng)該盡量避免print的使用韧骗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市零聚,隨后出現(xiàn)的幾起案子宽闲,更是在濱河造成了極大的恐慌,老刑警劉巖握牧,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異娩梨,居然都是意外死亡沿腰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門狈定,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颂龙,“玉大人,你說我怎么就攤上這事纽什〈肭叮” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵芦缰,是天一觀的道長企巢。 經(jīng)常有香客問我,道長让蕾,這世上最難降的妖魔是什么浪规? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮探孝,結(jié)果婚禮上笋婿,老公的妹妹穿的比我還像新娘。我一直安慰自己顿颅,他們只是感情好缸濒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般庇配。 火紅的嫁衣襯著肌膚如雪斩跌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天讨永,我揣著相機(jī)與錄音滔驶,去河邊找鬼。 笑死卿闹,一個(gè)胖子當(dāng)著我的面吹牛揭糕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锻霎,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼著角,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了旋恼?” 一聲冷哼從身側(cè)響起吏口,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冰更,沒想到半個(gè)月后产徊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜀细,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年舟铜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奠衔。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谆刨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出归斤,到底是詐尸還是另有隱情痊夭,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布脏里,位于F島的核電站她我,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏迫横。R本人自食惡果不足惜鸦难,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望员淫。 院中可真熱鬧合蔽,春花似錦、人聲如沸介返。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至刃宵,卻和暖如春衡瓶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牲证。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工哮针, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坦袍。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓十厢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捂齐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛮放,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容