Instrument
Time Profile(分析代碼的執(zhí)行時(shí)間筝尾,找出導(dǎo)致程序變慢的原因)
Separate by Thread
按線程分開做分析捡需,這樣更容易揪出那些吃資源的問題線程。特別是對(duì)于主線程筹淫,它要處理和渲染所有的接口數(shù)據(jù)站辉,一旦受到阻塞,程序必然卡頓或停止響應(yīng)损姜。
Invert Call Tree
反向輸出調(diào)用樹饰剥。把調(diào)用層級(jí)最深的方法顯示在最上面,更容易找到最耗時(shí)的操作摧阅。
Hide System Libraries
隱藏系統(tǒng)庫文件汰蓉。過濾掉各種系統(tǒng)調(diào)用,只顯示自己的代碼調(diào)用棒卷。
Flatten Recursion
拼合遞歸顾孽。將同一遞歸函數(shù)產(chǎn)生的多條堆棧(因?yàn)檫f歸函數(shù)會(huì)調(diào)用自己)合并為一條祝钢。
Top Functions
找到最耗時(shí)的函數(shù)或方法。
Allocations(內(nèi)存分配)
Category(類別)
通常是一個(gè) Core Foundation 對(duì)象若厚,OC類拦英、或原始內(nèi)存塊(block)。
Persistent Bytes(凈分配字節(jié)數(shù))
當(dāng)前已經(jīng)分配內(nèi)存但是仍然沒有被釋放的字節(jié)的總數(shù)测秸。
Persistent(凈分配數(shù))
當(dāng)前已經(jīng)分配內(nèi)存但仍然沒有被釋放的對(duì)象或內(nèi)存塊的數(shù)量疤估。
Transient(臨時(shí)分配數(shù))
當(dāng)前已經(jīng)分配內(nèi)存但仍然沒有被釋放的對(duì)象或內(nèi)存塊的數(shù)量。
Total Bytes(總分配字節(jié)數(shù))
所有已經(jīng)分配內(nèi)存,而且包括已經(jīng)被釋放了的字節(jié)的總數(shù)霎冯。
Total(總分配數(shù))
所有當(dāng)前已經(jīng)分配內(nèi)存,包括已經(jīng)被釋放了的對(duì)象或內(nèi)存 塊的總數(shù)铃拇。
Transient(臨時(shí)分配數(shù))
當(dāng)前和全部分配數(shù)的直方圖。如上圖所示當(dāng)比例變化時(shí),直方條會(huì)變顏色沈撞,Instruments 應(yīng)用通常給它們標(biāo)示不同的顏色來指出分配模式以便進(jìn)行進(jìn)一步的研 究慷荔。
Leaks檢查內(nèi)存泄露
Core Data
監(jiān)測(cè)讀取、緩存未命中关串、保存等操作拧廊,能直觀顯示是否保存次數(shù)遠(yuǎn)超實(shí)際需要。
Cocoa Layout
觀察約束變化晋修,找出布局代碼的問題所在吧碾。 Network:跟蹤 TCP / IP 和 UDP / IP 連接。
Automations
創(chuàng)建和編輯測(cè)試腳本來自動(dòng)化 iOS 應(yīng)用的用戶界面測(cè)試墓卦。
Core Animation(必須使用真機(jī))
Color Blended Layers(圖層混合)
檢測(cè)哪里發(fā)生了圖層混合倦春,并用紅色標(biāo)記出來。需要盡可能減少或者消除紅色區(qū)域落剪。
解決方法:
1睁本、backgroundColor屬性(最重要),如果不設(shè)置這個(gè)屬性忠怖,控件依然被認(rèn)為是透明的
2呢堰、opaque設(shè)置為YES,作用不是很大凡泣;但如果設(shè)置NO枉疼,影響卻很大
3、關(guān)閉alpha通道
注意:對(duì)于文字鞋拟,iOS8上用UILabel顯示中文卻出現(xiàn)了像素混合的情況骂维,因?yàn)樵趇OS8以前,UILabel使用的是CALayer作為底圖層贺纲,而在iOS8開始航闺,UILabel的底圖層變成了_UILabelLayer,繪制文本也有所改變。
解決方法:
背景色的四周多了一圈透明的邊潦刃,而這一圈透明的邊明顯超出了圖層的矩形區(qū)域侮措,設(shè)置圖層的masksToBounds為YES時(shí),圖層將會(huì)沿著Bounds進(jìn)行裁剪福铅,就可以了
Color Hits Green and Misses Red(光柵化)
它表示如果命中緩存則顯示為綠色萝毛,否則顯示為紅色项阴,顯然綠色越多越好滑黔,紅色越少越好
- 光柵化是將一個(gè)layer預(yù)先渲染成位圖(bitmap),然后加入緩存中环揽。如果對(duì)于陰影效果這樣比較消耗資源的靜態(tài)內(nèi)容進(jìn)行緩存略荡,可以得到一定幅度的性能提升。demo中的這一行代碼表示將label的layer光柵化:label.layer.shouldRasterize = true歉胶。
光柵化的核心在于緩存的思想汛兜,因?yàn)閘ayer進(jìn)行光柵化后渲染成位圖放在緩存中。當(dāng)屏幕出現(xiàn)滑動(dòng)時(shí)通今,我們直接從緩存中讀取而不必渲染粥谬,所以會(huì)看到綠色。當(dāng)新的label出現(xiàn)時(shí)辫塌,緩存中沒有個(gè)這個(gè)label的位圖漏策,所以會(huì)變成紅色。第三點(diǎn)比較關(guān)鍵臼氨,緩存中的對(duì)象有效期只有100ms掺喻,即如果在0.1s內(nèi)沒有被使用就會(huì)自動(dòng)從緩存中清理出去。這就是為什么停留一會(huì)兒再滑動(dòng)就會(huì)看到紅色储矩。
光柵化的緩存機(jī)制是一把雙刃劍感耙,先寫入緩存再讀取有可能消耗較多的時(shí)間。因此光柵化僅適用于較復(fù)雜的持隧、靜態(tài)的效果即硼。光柵化會(huì)導(dǎo)致離屏渲染
Color Copied Images(顏色格式)
比如應(yīng)用中有一些從網(wǎng)絡(luò)下載的圖片,而GPU恰好不支持這個(gè)格式屡拨,這就需要CPU預(yù)先進(jìn)行格式轉(zhuǎn)化只酥。“Color Copied Images”就用來檢測(cè)這種實(shí)時(shí)的格式轉(zhuǎn)化洁仗,如果有則會(huì)將圖片標(biāo)記為藍(lán)色层皱,說明圖片格式出現(xiàn)了一些問題。
背景:像素在內(nèi)存中的布局和它在磁盤中的存儲(chǔ)方式并不相同赠潦〗信郑考慮一種簡(jiǎn)單的情況:每個(gè)像素有R、G她奥、B和alpha四個(gè)值瓮增,每個(gè)值占用1字節(jié)怎棱,因此每個(gè)像素占用4字節(jié)的內(nèi)存空間。一張1920*1080的照片(iPhone6 Plus的分辨率)一共有2,073,600個(gè)像素绷跑,因此占用了超過8Mb的內(nèi)存拳恋。但是一張同樣分辨率的PNG格式或JPEG格式的圖片一般情況下不會(huì)有這么大。這是因?yàn)镴PEG將像素?cái)?shù)據(jù)進(jìn)行了一種非常復(fù)雜且可逆的轉(zhuǎn)化砸捏。
當(dāng)我們打開JPEG格式的圖片時(shí)谬运,CPU會(huì)進(jìn)行一系列運(yùn)算,將JPEG圖片解壓成像素?cái)?shù)據(jù)垦藏。顯然這個(gè)工作會(huì)消耗不少時(shí)間梆暖,所以不應(yīng)該在滑動(dòng)時(shí)進(jìn)行,我們應(yīng)該預(yù)先處理好圖片掂骏。
Color Misaligned Images(圖片大泻洳怠)
它表示如果圖片需要縮放則標(biāo)記為黃色,如果沒有像素對(duì)齊則標(biāo)記為紫色弟灼。
這個(gè)優(yōu)化是調(diào)整所有圖片的像素大小以避免不必要的縮放级解。我們要盡可能保證無論是本地圖片還是從網(wǎng)絡(luò)或取得圖片的大小,都與其frame保持一致田绑。
Color Offscreen-Rendered Yellow(離屏渲染)
離屏渲染的地方標(biāo)記為黃色勤哗。離屏渲染意味著把渲染結(jié)果臨時(shí)保存,等用到時(shí)再取出辛馆,因此相對(duì)于普通渲染更占用資源俺陋。
離屏渲染可能會(huì)自動(dòng)觸發(fā),也可以手動(dòng)觸發(fā)昙篙。以下情況可能會(huì)導(dǎo)致觸發(fā)離屏渲染:
1. 重寫drawRect方法
2. 有mask或者是陰影(layer.masksToBounds, layer.shadow*)腊状,模糊效果也是一種mask
3. layer.shouldRasterize = true
前兩者會(huì)自動(dòng)觸發(fā)離屏渲染,第三種方法是手動(dòng)開啟離屏渲染苔可。
設(shè)置cornerRadius本身并不會(huì)導(dǎo)致離屏渲染缴挖,但很多時(shí)候它還需要配合layer.masksToBounds = true使用。根據(jù)之前的總結(jié)焚辅,設(shè)置masksToBounds會(huì)導(dǎo)致離屏渲染映屋。解決方案是盡可能在滑動(dòng)時(shí)避免設(shè)置圓角,如果必須設(shè)置圓角同蜻,可以使用光柵化技術(shù)將圓角緩存起來:
// 設(shè)置圓角
label.layer.masksToBounds = true
label.layer.cornerRadius = 8
label.layer.shouldRasterize = true
label.layer.rasterizationScale = layer.contentsScale
Color Compositing Fast-Path Blue(快速路徑)
用于標(biāo)記由硬件繪制的路徑棚点,藍(lán)色越多越好
離屏渲染的最后一步是把此前的多個(gè)路徑組合起來。如果這個(gè)組合過程能由CPU完成湾蔓,就會(huì)大量減少GPU的工作瘫析。這種技術(shù)在繪制地圖中可能用到。
Flash updated Regions(變化區(qū)域)
用于標(biāo)記發(fā)生重繪的區(qū)域。 一個(gè)典型的例子是系統(tǒng)的時(shí)鐘應(yīng)用贬循,絕大多數(shù)時(shí)候只有顯示秒針的區(qū)域需要重繪:刷新視圖時(shí)咸包,我們應(yīng)該把需要重繪的區(qū)域盡可能縮小,對(duì)于未發(fā)生變化的內(nèi)容則不應(yīng)該重繪杖虾。
總結(jié):
優(yōu)化滑動(dòng)性能主要涉及三個(gè)方面:
1烂瘫、避免圖層混合
* 確保控件的opaque屬性設(shè)置為true奇适,確保backgroundColor和父視圖顏色一致且不透明坟比。
* 如無特殊需要,不要設(shè)置低于1的alpha值滤愕。
* 確保UIImage沒有alpha通道温算。
2、避免臨時(shí)轉(zhuǎn)換
* 確保圖片大小和frame一致间影,不要在滑動(dòng)時(shí)縮放圖片。
* 確保圖片顏色格式被GPU支持茄茁,避免勞煩CPU轉(zhuǎn)換魂贬。
3、慎用離屏渲染
* 絕大多數(shù)時(shí)候離屏渲染會(huì)影響性能裙顽。
* 重寫drawRect方法付燥,設(shè)置圓角、陰影愈犹、模糊效果键科,光柵化都會(huì)導(dǎo)致離屏渲染。
* 設(shè)置陰影效果是加上陰影路徑漩怎。
* 滑動(dòng)時(shí)若需要圓角效果勋颖,開啟光柵化。