檢測iOS的APP效能的一些方法

發表於2016-03-30

首先如果遇到應用卡頓或者因為記憶體佔用過多時一般使用Instruments裡的來進行檢測。但對於複雜情況可能就需要用到子執行緒監控主執行緒的方式來了,下面我對這些方法做些介紹:

Time Profiler

可以檢視多個執行緒裡那些方法費時過多的方法。先將右側Hide System Libraries打上勾,這樣能夠過濾資訊。然後在Call Tree上會預設按照費時的執行緒進行排序,單個執行緒中會也會按照對應的費時方法排序,選擇方法後能夠通過右側Heaviest Stack Trace裡雙擊檢視到具體的費時操作程式碼,從而能夠有針對性的優化,而不需要在一些本來就不會怎麼影響效能的地方過度優化。

Allocations

這裡可以對每個動作的前後進行Generations,對比記憶體的增加,檢視使記憶體增加的具體的方法和程式碼所在位置。具體操作是在右側Generation Analysis裡點選Mark Generation,這樣會產生一個Generation,切換到其他頁面或一段時間產生了另外一個事件時再點Mark Generation來產生一個新的Generation,這樣反覆,生成多個Generation,檢視這幾個Generation會看到Growth的大小,如果太大可以點進去檢視相應占用較大的執行緒裡右側Heaviest Stack Trace裡檢視對應的程式碼塊,然後進行相應的處理。

Leak

可以在上面區域的Leaks部分看到對應的時間點產生的溢位,選擇後在下面區域的Statistics>Allocation Summary能夠看到洩漏的物件,同樣可以通過Stack Trace檢視到具體對應的程式碼區域。

開發時需要注意如何避免一些效能問題

NSDateFormatter

通過Instruments的檢測會發現建立NSDateFormatter或者設定NSDateFormatter的屬性的耗時總是排在前面,如何處理這個問題呢,比較推薦的是新增屬性或者建立靜態變數,這樣能夠使得建立初始化這個次數降到最低。還有就是可以直接用C,或者這個NSData的Category來解決https://github.com/samsoffes/sstoolkit/blob/master/SSToolkit/NSData%2BSSToolkitAdditions.m

UIImage

這裡要主要是會影響記憶體的開銷,需要權衡下imagedNamed和imageWithContentsOfFile,瞭解兩者特性後,在只需要顯示一次的圖片用後者,這樣會減少記憶體的消耗,但是頁面顯示會增加Image IO的消耗,這個需要注意下。由於imageWithContentsOfFile不快取,所以需要在每次頁面顯示前載入一次,這個IO的操作也是需要考慮權衡的一個點。

頁面載入

如果一個頁面內容過多,view過多,這樣將長頁面中的需要滾動才能看到的那個部分檢視內容通過開啟新的執行緒同步的載入。

優化首次載入時間

通過Time Profier可以檢視到啟動所佔用的時間,如果太長可以通過Heaviest Stack Trace找到費時的方法進行改造。

監控卡頓的方法

還有種方法是在程式裡去監控效能問題。可以先看看這個Demo,地址https://github.com/ming1016/DecoupleDemo。 這樣在上線後可以通過這個程式將使用者的卡頓操作記錄下來,定時發到自己的伺服器上,這樣能夠更大範圍的收集效能問題。眾所周知,使用者層面感知的卡頓都是來自處理所有UI的主執行緒上,包括在主執行緒上進行的大計算,大量的IO操作,或者比較重的繪製工作。如何監控主執行緒呢,首先需要知道的是主執行緒和其它執行緒一樣都是靠NSRunLoop來驅動的。可以先看看CFRunLoopRun的大概的邏輯

根據這個RunLoop我們能夠通過CFRunLoopObserverRef來度量。用GCD裡的dispatch_semaphore_t開啟一個新執行緒,設定一個極限值和出現次數的值,然後獲取主執行緒上在kCFRunLoopBeforeSources到kCFRunLoopBeforeWaiting再到kCFRunLoopAfterWaiting兩個狀態之間的超過了極限值和出現次數的場景,將堆疊dump下來,最後發到伺服器做收集,通過堆疊能夠找到對應出問題的那個方法。

有時候造成卡頓是因為資料異常,過多,或者過大造成的,亦或者是操作的異常出現的,這樣的情況可能在平時日常開發測試中難以遇到,但是在真實的特別是使用者受眾廣的情況下會有人出現,這樣這種收集卡頓的方式還是有價值的。

堆疊dump的方法

第一種是直接呼叫系統函式獲取棧資訊,這種方法只能夠獲得簡單的資訊,沒法配合dSYM獲得具體哪行程式碼出了問題,型別也有限。這種方法的主要思路是signal進行錯誤訊號的獲取。程式碼如下

使用PLCrashReporter的話出的報告看起來能夠定位到問題程式碼的具體位置了。

下面是測試Demo裡堆疊裡的內容

相關文章