概述
Time Profiler主要用來檢測應(yīng)用CPU的使用情況,可以幫助我們分析代碼/方法的執(zhí)行時(shí)間,找出程序變慢的原因,告訴我們時(shí)間都去哪了
在開發(fā)過程中,點(diǎn)擊按鈕,或者跳轉(zhuǎn)頁面時(shí)有卡頓,即延遲,就可以使用Time Profiler找出耗時(shí)的函數(shù)
原理
Time Profiler是按照固定時(shí)間間隔(1ms)來跟蹤每一個(gè)線程的調(diào)用堆棧信息進(jìn)行采樣,然后通過統(tǒng)計(jì)比較時(shí)間間隔之間的堆棧狀態(tài),來推算某個(gè)方法的執(zhí)行時(shí)間,并獲取一個(gè)近似值。如下所示,圖中虛線是采樣點(diǎn),最后統(tǒng)計(jì)出調(diào)用棧和對應(yīng)函數(shù)調(diào)用的次數(shù)

從圖中看出,method3并不在統(tǒng)計(jì)結(jié)果中,這說明只要方法運(yùn)行的足夠快時(shí),是很可能無法統(tǒng)計(jì)到的。對于耗時(shí)分析來說,并不會有什么問題,因?yàn)橹饕欠治鰣?zhí)行慢的方法,執(zhí)行快的方法一般都不會引起性能問題。
而且Time Profiler并不會精確的統(tǒng)計(jì)出方法的執(zhí)行時(shí)間,當(dāng)線程處于掛起或者等待執(zhí)行狀態(tài)時(shí),Time Profiler并不能統(tǒng)計(jì)到此時(shí)的線程,它只能統(tǒng)計(jì)到真正在CPU上執(zhí)行的線程
注意事項(xiàng)
1、必須在iOS真機(jī)上調(diào)試
因?yàn)槟M器是運(yùn)行在Mac上的,然后Mac的CPU一般都比iOS設(shè)備快,兩者的GPU也完全不同,所以如果在模擬器上進(jìn)行調(diào)試,會導(dǎo)致模擬器的性能數(shù)據(jù)和用戶真機(jī)的數(shù)據(jù)相差甚遠(yuǎn)。
2、必須在release環(huán)境下調(diào)試
主要是因?yàn)閄code在debug環(huán)境下會禁用Watch Dog。而在release環(huán)境打包時(shí),編譯器會引入一系列提高性能的優(yōu)化,例如去掉調(diào)試符號、移除并重組代碼等。同時(shí),iOS引入了Watch Dog(看門狗)機(jī)制,在不同的場景下,Watch Dog會監(jiān)測應(yīng)用的性能,如果超出了該場景所規(guī)定的的運(yùn)行時(shí)間,Watch Dog會強(qiáng)制終結(jié)App的進(jìn)程。開發(fā)者可以看到對應(yīng)的crash log。
使用
- 創(chuàng)建兩個(gè)頁面A和B,從Apush到B,在B的viewDidLoad方法中調(diào)用下面的方法
- (void)testLongTime{
for (int i = 1; i < 10000000; i ++) {
NSLog(@"i = %d", i);
}
}
-
通過Xcode - Product - Profile - 選擇Time Profiler,配置Call Tree
Instruments_07_02.png- Separate by State:按狀態(tài)分開,分析數(shù)據(jù)。
- Separate by Thread(建議選擇):線程分離,只有這樣才能在調(diào)用路徑中能夠清晰看到占用CPU最大的線程.每個(gè)線程應(yīng)該分開考慮。只有這樣你才能揪出那些大量占用CPU的"重"線程,按線程分開做分析,這樣更容易揪出那些吃資源的問題線程。特別是對于主線程,它要處理和渲染所有的接口數(shù)據(jù),一旦受到阻塞,程序必然卡頓或停止響應(yīng)。
- Invert Call Tree(不建議選擇)反向顯示調(diào)用:調(diào)用樹倒返過來,將習(xí)慣性的從根向下一級一級的顯示,如選上就會返過來從最底層調(diào)用向一級一級的顯示。如果想要查看那個(gè)方法調(diào)用為最深時(shí)使用會更方便些。
- Hide System Libraries(建議選擇)隱藏系統(tǒng)庫:選上它只會展示與應(yīng)用有關(guān)的符號信息,一般情況下我們只關(guān)心自己寫的代碼所需的耗時(shí),而不關(guān)心系統(tǒng)庫的CPU耗時(shí)。
- Flatten Recursion(一般不選)合并遞歸:選上它會將調(diào)用棧里遞歸函數(shù)作為一個(gè)入口。
- Top Functions(可選)置頂耗時(shí)方法:選上它會將最耗時(shí)的函數(shù)降序排列,而這種耗時(shí)是累加的,比如A調(diào)用了B,那么A的耗時(shí)數(shù)是會包含B的耗時(shí)數(shù)。
-
點(diǎn)擊左上角運(yùn)行程序,開啟耗時(shí)檢測,運(yùn)行結(jié)果如下
Instruments_07_03.png
從圖中可以看出,大部分時(shí)間占用在-[SecondViewController testLongTime]方法中,雙擊進(jìn)入源代碼頁面,可以具體查看某一行的占用情況
Instruments_07_04.png
如果選擇匯編展示
Instruments_07_05.png
如果選擇查看次數(shù)
Instruments_07_06.png -
還可以進(jìn)一步設(shè)置耗時(shí)范圍,過濾出想要的數(shù)據(jù),比如設(shè)置最小耗時(shí)為50,過濾50以下的
Instruments_07_07.png
所以綜上所述,Time Profiler的基本調(diào)試邏輯為
- 運(yùn)行項(xiàng)目,開始分析
- 找到最大的占用函數(shù)
- 修復(fù)耗時(shí)的方法
- 繼續(xù)分析...直到完全修復(fù)
- 注:有時(shí)自定義的方法也會引起系統(tǒng)代碼卡頓,所以查看系統(tǒng)庫的耗時(shí)方法也是很有必要的
參考文章
iOS性能優(yōu)化 - 工具Instruments之Time Profiler
iOS 性能優(yōu)化 - TimeProfiler分析代碼耗時(shí)
ios Instruments之Time Profiler
iOS App啟動優(yōu)化(二)—— 使用“Time Profiler”工具監(jiān)控App的啟動耗時(shí)





