iOS監控:資源使用

林欣達發表於2017-05-09

前言

應用效能的衡量標準有很多,從使用者的角度來看,卡頓是最明顯的表現,但這不意味看起來不卡頓的應用就不存在效能問題。從開發角度來看,衡量一段程式碼或者說演算法的標準包括空間複雜度和時間複雜度,分別對應記憶體和CPU兩種重要的計算機硬體。只有外在與內在都做沒問題,才能說應用的效能做好了。因此,一套應用效能監控系統對開發者的幫助是巨大的,它能幫助你找到應用的效能瓶頸。

iOS監控:資源使用

CPU

執行緒是程式執行的最小單位,換句話來說就是:我們的應用其實是由多個執行在CPU上面的執行緒組合而成的。要想知道應用佔用了CPU多少資源,其實就是獲取應用所有執行緒佔用CPU的使用量。結構體thread_basic_info封裝了單個執行緒的基本資訊:

問題在於如何獲取這些資訊。iOS的作業系統是基於Darwin核心實現的,這個核心提供了task_threads介面讓我們獲取所有的執行緒列表以及介面thread_info來獲取單個執行緒的資訊:

第一個函式的target_task傳入程式標記,這裡使用mach_task_self()獲取當前程式,後面兩個傳入兩個指標分別返回執行緒列表和執行緒個數,第二個函式的flavor通過傳入不同的巨集定義獲取不同的執行緒資訊,這裡使用THREAD_BASIC_INFO。此外,引數存在多種型別,實際上大多數都是mach_port_t型別的別名:

iOS監控:資源使用

因此可以得到下面的程式碼來獲取應用對應的CPU佔用資訊。巨集定義TH_USAGE_SCALE返回CPU處理總頻率:

記憶體

程式的記憶體使用資訊同樣放在了另一個結構體mach_task_basic_info中,儲存了包括多種記憶體使用資訊:

對應的獲取函式名為task_info,傳入程式名、獲取的資訊型別、資訊儲存結構體以及數量變數:

由於mach_task_basic_info中的記憶體使用bytes作為單位,在顯示之前我們還需要進行一層轉換。另外為了方便實際使用中的換算,筆者使用結構體來儲存記憶體相關資訊:

獲取記憶體佔用量的程式碼如下:

展示

記憶體和CPU的監控並不像其他裝置資訊一樣,能做更多有趣的事情。實際上,這兩者的獲取是一段枯燥又固定的程式碼,因此並沒有太多可說的。對於這兩者的資訊,基本上是開發階段展示出來觀察效能的。因此設定一個良好的查詢週期以及展示是這個過程中相對好玩的地方。筆者最終監控的效果如下:

iOS監控:資源使用

不知道什麼原因導致了task_info獲取到的記憶體資訊總是比Xcode自身展示的要多20M左右,因此使用的時候自行扣去這一部分再做衡量。為了保證展示器總能顯示在頂部,筆者建立了一個UIWindow的單例,通過設定windowLevel的值為CGFLOAT_MAX來保證顯示在最頂層,並且重寫了一部分方法保證不被修改:

三個標籤欄採用非同步繪製的方式保證更新文字的時候不影響主執行緒,核心程式碼:

其他

除了監控應用本身佔用的CPU和記憶體資源之外,Darwin提供的介面還允許我們去監控整個裝置本身的記憶體和CPU使用量,筆者分別封裝了額外兩個類來獲取這些資料。最後統一封裝了LXDResourceMonitor類來監控這些資源的使用,通過列舉來控制監控內容:

這裡使用到了位運算的內容,相比起其他的手段要更簡潔高效。APM系列至此已經完成了大半,當然除了網上常用的APM手段之外,筆者還會加入包括RunLoop優化運用相關的技術。

Demo在此

相關文章