本系列博文 基於是前微信高階工程師張紹文專欄 《Android開發高手課》的讀書筆記。
文章所寫內容是本人讀完的感悟,需要原文的朋友請自行購買。
卡頓優化篇
先貼兩篇比較簡單的分析文章
下面進入正題
卡頓根本原因
造成卡頓的原因可能有千百種,不過最終都會反映到CPU 時間上.
CPU時間分兩種
- 使用者時間 執行使用者態應用程式程式碼所消耗的時間
- **系統時間 **執行核心態系統呼叫所消耗的時間,包括 I/O、鎖、中斷以及其他系統呼叫時間
CPU使用狀態有以下幾個指標
-
CPU 使用率: 如果 CPU 使用率長期大於 60% ,表示系統處於繁忙狀態,就需要進一步分析使用者時間和系統時間的比例。對於普通應用程式,系統時間不會長期高於 30%,如果超過這個值,就得考慮是否I/O呼叫過多或者鎖呼叫的過於頻繁的問題。(Android studio 3.0的版本之後可以直接觀測到CPU的使用情況)
-
CPU 飽和度: CPU 飽和度反映的是執行緒排隊等待 CPU 的情況,也就是 CPU 的負載情況。
CPU 飽和度首先會跟應用的執行緒數有關,如果啟動的執行緒過多,易導致系統不斷地切換執行的執行緒,把大量的時間浪費在上下文切換,要知道每一次 CPU 上下文切換都需要重新整理暫存器和計數器,至少需要幾十納秒的時間。
卡頓排查工具
分兩個流派,instrument和sample.
- instrument: 獲取一段時間內所有函式的呼叫過程,可以通過分析這段時間內的函式呼叫流程,再進一步分析待優化的點。
- sample: 有選擇性或者採用抽樣的方式觀察某些函式呼叫過程,可以通過這些有限的資訊推測出流程中的可疑點,然後再繼續細化分析。
具體的工具如下:
Traceview
屬於instrument派系,利用 Android Runtime 函式呼叫的 event 事件,將函式執行的耗時和呼叫關係寫入 trace 檔案中。
Traceview屬於比較早起的工具,效能開銷過大,有時無法反映真實的執行狀況,另外無法反混淆。
在Android 5.0之後,新增了 sample型別,減少開銷,但是資訊量就不一定達到分析需求了。
Nanoscope
相比起Traceview,Uber開源的Nanoscope的效能消耗就小了許多。
但由於Nanoscope是直接修改Android虛擬機器原始碼,會有不少的侷限性。
比如需要自己刷ROM或者用它提供的x86的模擬器,就算自己刷ROM也只支援Nexus 6P。
如果想要簡便的使用Nanoscope的話,需要一系列自動化腳步協助。
systrace
systrace則是利用Linux的ftrace除錯工具,相當於在系統各個關鍵位置都新增了一些效能探針.
一說到Linux可能很多人就比較蒙,拿Android下的知識來講,你可以理解為類似Activity Manager類似的監控。
Simpleperf
Native函式的監控.(不瞭解)
卡頓監控
張老師在課中講的多是比較深入的知識和解決問題的思路。
就好比一個應用滿分100分,張老師講的是如何把應用從90分拉向100分.
然而實際上大部分人需要的是如何到90分.
任重而道遠
微信的卡頓監控也經過了幾個過程
訊息佇列監控
-
最開始通過替換主現場訊息佇列中Looper的MessageLogging來獲取卡頓時間。
以及列印對應的函式資訊
//參考的程式碼 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } 複製程式碼
實現原理可以參考BlockCanary這個庫或者這篇博文 Android卡頓檢查-BlockCanary淺析
-
上線之後發現效能有所下降,替換方案。
開一個監控執行緒,每隔1s向主執行緒訊息頭插入一條空訊息,1秒後去檢查主現程頭部是否是之前插入的空訊息。如果是,說明主執行緒卡頓了0~1秒,為什麼會是一個區間呢?因為你傳送空訊息的時候也需要考慮在內。
那如果監控一個3秒的卡頓,在第4秒的時候去檢查空訊息是否被消費,如果沒有,說明確實發生了一個3秒以上的卡頓。
訊息佇列監控也存在一些問題。
比如主執行緒卡頓了3秒,在這3秒鐘有多個函式,而通過這種方式只能得到最後一個函式的一些資訊.
但實際上耗時比較久的函式不一定是最後一個.
不過對於使用者量比較大的應用來說,根據反饋回來的資料比例還是能得到具體耗時的函式是那個。
插樁
利用lnline Hook技術和上文中提到systrace。
Profile
FaceBook開源的Profile庫,效能確實很高。
但是其中黑科技太多,所以相容性還是個大問題。
幀率監控
業界都使用 Choreographer 來監控應用的幀率
監聽介面是否存在繪製行為
getWindow().getDecorView().getViewTreeObserver().addOnDrawListener
複製程式碼
Android Vitals 將連續丟幀超過 700 毫秒定義為凍幀,也就是連續丟幀 42 幀以上。
其他
4大元件中 Service 和 Receiver 雖然是後臺元件,不過它們生命週期也是佔用主執行緒的,呼叫的過於頻繁也會導致卡頓.
最後,給自己公眾號打個廣告,【碼農的嘮叨】聊技術,聊熱文,聊網際網路趣事,也發嘮叨