天天看點

iOS性能分析和優化

前言: 随着項目的擴大和功能的增多,代碼沒有經過嚴格的調試和優化,要麼任性地卡頓運作,要麼就低調地崩潰,最後導緻使用者用着不開心,開發者也比較煩惱。

為了突破這個這個關卡其實并不難,首先開發者隻要在Xcode自帶的監控調試工具 Instruments 上花點功夫就能夠讓代碼順暢運作。工欲善其事,必先利其器。Instrument對于iOS開發來說,是發現并且解決問題的一把利器。Instruments 提供了很多檢測功能,重點介紹一下我常用的幾大類:

  • Analyze—靜态分析
  • Leaks—記憶體洩露(動态記憶體洩露檢測)
  • Time Profiler:檢測分析代碼的執行時間

界面顯示的原理

iOS裝置通常是60fps(每秒60幀),也就是說兩幀相隔的時間是1/60秒,大概16.7ms。在這16.7ms中,為了顯示一幀,需要如下工作

CPU計算好各個視圖的位置,大小,對圖檔進行解碼等,繪制成紋理交給GPU

GPU對收到的紋理進行混合,頂點變換,渲染到幀緩沖區

每16.7ms,一個時鐘信号到達,幀緩沖區取出一幀,顯示到螢幕。

也就是說,CPU或者GPU被大量占用的時候,都有可能在16.7ms中沒辦法完成一幀的繪制,導緻時鐘信号到來的時候,取得還是上一幀的内容,也就都有可能導緻界面卡頓

離屏渲染

在iOS中,渲染通常分為CPU和GPU渲染兩種,而GPU渲染又分為在GPU緩沖區和非GPU緩沖區兩種

CPU渲染(軟體渲染),CPU繪制成bitmap,交給GPU

GPU渲染(硬體渲染)

GPU緩沖區渲染

非GPU緩沖區渲染(額外開辟緩沖區)

通常,CPU渲染,和GPU非幀緩沖區内渲染統稱為離屏渲染。因為,CPU和幀緩沖區是為圖形圖像顯示做了高度優化的,速度較快。

什麼情況下會觸發離螢幕渲染?

用CoreGraphics的CGContext繪制的

在drawRect中繪制的,即使drawRect是空的

Layer具有Mask(比如圓角)或者Shadow

Layer的隔栅化shouldRasterize為True

文本(UILabel,UITextfield,UITextView,CoreText,UITextLayer等)

一,Analyze—靜态分析

顧名思義,靜态分析不需要運作程式,就能檢查到存在記憶體洩露的地方。

1. 使用方法:打開Xcode,command + shift + B;或者Xcode - Product - Analyze;

2. 常見的三種洩露情形:

(1)建立了一個對象,但是并沒有使用。Xcode提示資訊: Value Stored to 'number' is never read 。翻譯一下:存儲在'number'裡的值從未被讀取過。

(2)建立了一個(指針可變的)對象,且初始化了,但是初始化的值一直沒讀取過。Xcode提示資訊: Value Stored to 'str' during its initialization is never read

(3)調用了讓某個對象引用計數加1的函數,但沒有調用相應讓其引用計數減1的函數。Xcode提示資訊: Potential leak of an object stored into 'subImageRef' 。 翻譯一下:subImageRef對象的記憶體單元有潛在的洩露風險。

iOS性能分析和優化

iOS性能分析和優化

二,Leaks—記憶體洩露

Leaks是動态的記憶體洩露檢查工具,需要一邊運作程式,一邊檢測。

1.使用方法: 進入Xcode,command + control + i ;或者Xcode - Xcode - Open Developer Tool - Instruments; 或者Xcode - Product - Profile。選擇Leaks。

一般用靜态分析檢查過的代碼,記憶體洩露都比較少。測試了有3個項目能點的按鈕都點了,能進的頁面都進的,Leaks也沒檢測到洩露。

三,Time Profile

1,打開Time Profile,然後運作想要分析的App

iOS性能分析和優化

iOS性能分析和優化

2.進入主界面,上下滾動List,讓Time Profile采集資料,勾選右側的Separate by Thread,按線程區分Invert Call Tree,逆向Call Tree,友善我們檢視方法調用順序Hide System Libraries,隐藏系統的庫,因為通常系統的代碼并不會影響性能

iOS性能分析和優化

iOS性能分析和優化

3.可以選擇一段時間,來分析這段時間CPU的使用情況

iOS性能分析和優化

iOS性能分析和優化

4.找到占用時間最多的代碼

iOS性能分析和優化

iOS性能分析和優化

然後,輕按兩下占用最多的這一行,進入實際的代碼,看看到底哪裡占用比較多

iOS性能分析和優化

iOS性能分析和優化

這裡,我們看到是這一行代碼cell.testLabel?.attributedText = mutableAttr。

占用最多的CPU時間。

我們先來看下整個方法代碼,

TableViewCell其實很簡單,就一個ImageView(帶圓角,陰影),一個UILabel

cellForRowAtIndexPath裡會随機的生成100個字元,然後用AttributeText來讓UILabel顯示

乍一看,問題應該是這個随機生成100個字元的函數啊

iOS性能分析和優化

iOS性能分析和優化

因為,每一次CellForRow調用的時候,都會計算100次。然後,我們實際分析的時候,發現其實100次對顯示來說,真不算什麼,也不是卡頓的原因。

那麼,為什麼設定attributeText占用時間這麼多呢?

其實很簡單,attributeText是建立在TextKit上的,由于每一次顯示都是随機的attributeText,每一次都要重新計算文本的大小,位置等等。另外,UIKit中,提供的文本渲染都是在CPU中進行的,渲染成Bitmap,然後交給GPU,是以導緻設定attributeText的時候,占用很多時間。

這裡不得不提到:一定不要過早優化,優化的時候盡量依賴于Instrument的分析結果,而不是自己的主觀感受。尤其當你還是個新司機的時候。