iOS 性能優化 - TimeProfiler分析代碼耗時

一: Time Profiler

Time Profiler用來分析代碼的執行時間,主要用來分析CPU使用情況。
注意:要在release模式(或者自定義的其他的打包模式)下分析,原因在release模式下:

    1. 會開啟編譯器優化,提高代碼運行效率
    1. 生成調試的符號表,這樣才能夠在profile的時候看到代碼的調用棧
    1. 多數條件編譯只會在debug模式下生效,release模式和生產環境是一樣的。

二: 原理

Time Profiler每隔1ms會對線程的調用棧采樣,然后用統計學的方式去做出分析。

image

圖中虛線是采樣點,最后統計出調用棧和對應函數出現的個數。

從圖中不難看出,method3并沒有出現在統計結果中,也就意味著方法運行的足夠快的時候,很有可能統計不到,但這對于分析來說并不會有太大影響,因為運行快的方法往往不會引起性能問題。

Tips:Time Profiler并不會精確的統計出方法的執行時間,當線程處于掛起和等待執行的狀態時候,timer profiler并不能統計到,它只能統計到真正在CPU上執行的。

三: Demo

Demo工程是一個簡易的相冊應用,故意寫的很爛,包含了三個界面:

? 第一個界面只提供一個入口

? main界面用瀑布流的方式提供圖片預覽,圖片被加了濾鏡

? detail界面可以查看大圖

image
image
image

在iPhone 6上運行,在進入main界面的時候會看到明顯的卡頓:


image

我們通過Time Profile來找到原因:Product -> Profile

這會讓XCode執行一次Release的build,然后啟動Instrument

image

我們選擇Time Profiler啟動,然后正常操作App,采集到了數據后,停止Instrument。

image

對圖中的幾點說明:

  • 各個線程的采集數據匯總
  • 點擊1中的某一行,可以看到采集到的堆棧,注意2區域的右上角,可以選擇隱藏系統的符號
  • 可以選擇關注的隊列/CPU等。
  • 可以用pinch手勢來放大縮小時間范圍,鼠標可以拖動選擇一段區域

Tips:
Weight表示占用全部的百分比
Self Wight表示當前方法執行占用的百分比,如果看到是0,表示當前方法其實不占用什么時間,時間都是子程序調用占用的。

我們用鼠標拖動,選擇選擇CPU占用較高的部分,可以看到堆棧如下:

image

Tips: 按住Option,然后鼠標左鍵點圖中的箭頭,可以快速展開。

從圖中看到:大部分時間占用在-[MainController loadAllImages]這個方法:讀取本地圖片,然后對圖加濾鏡

- (void)loadAllImages{
    NSMutableArray * images = [NSMutableArray new];
    for (long i = 1; i < 40; i++) {
        NSString * imageName = [NSString stringWithFormat:@"image_%ld",i % 20 + 1];
        NSString * imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"jpeg"];
        UIImage * image = [UIImage imageWithContentsOfFile:imagePath];
        [images addObject:[self filterdImage:image]];
    }
    self.images = [images copy];
}

我們可以勾選以下選項,來看得更清楚一些:

  • Hide System Libraries 隱藏系統的庫
  • Invert Call Tree 倒置函數隊戰
image

勾選后

image

Timer Profiler的基本debug邏輯:分析 -> 找到最大的占用函數 -> 修復 -> 繼續分析…,直到完全修復。有時候自己的代碼會引起系統代碼卡頓,所以查看系統庫的卡頓也很有必要的。

可以通過雙擊一行,進入源代碼界面,看看具體某一行的占用情況:


image

也可以選擇查看次數:


image

查看次數:

image

或者,查看反匯編

image

四: FAQ

為什么我在Time Profiler看不到類和方法的名稱呢?

絕大部分原因是你的打包模式沒有開啟dSYM或者debug symbols

image
為什么明明我的App很卡,可是用Time Profiler分析卻找不到相關代碼?

卡頓的原因主要分為兩大類:CPU瓶頸和GPU瓶頸

當界面有大量的shadow,mask或者有非常多的View/Layer,GPU渲染紋理和頂點的時候可能會有壓力,這時候應該用Core Animation觀察GPU的使用率。

CPU引起的卡頓大多可以通過Time Profiler找到,如果找不到可能的原因有兩個:

  • 代碼引起了大量系統調用,占用CPU時間,這種情況你需要仔細分析Time Profiler中的系統占用。
  • 頻繁的鎖和線程切換。因為線程被掛起的時候,time profiler無法采樣到,這種情況可以通過System Trace分析。

摘自:黃文臣博客-TimeProfiler分析代碼耗時
TimeProfilerdemo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容