讀書筆記3-卡頓優化篇

niknowzcd發表於2019-03-01

本系列博文 基於是前微信高階工程師張紹文專欄 《Android開發高手課》的讀書筆記。

文章所寫內容是本人讀完的感悟,需要原文的朋友請自行購買。

卡頓優化篇

先貼兩篇比較簡單的分析文章

Android效能優化-介面渲染原理淺析

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.

  1. instrument: 獲取一段時間內所有函式的呼叫過程,可以通過分析這段時間內的函式呼叫流程,再進一步分析待優化的點。
  2. 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分.

任重而道遠

微信的卡頓監控也經過了幾個過程

訊息佇列監控

  1. 最開始通過替換主現場訊息佇列中Looper的MessageLogging來獲取卡頓時間。

    以及列印對應的函式資訊

    //參考的程式碼
    Printer logging = me.mLogging;
    if (logging != null) {
        logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
    }
    複製程式碼

實現原理可以參考BlockCanary這個庫或者這篇博文 Android卡頓檢查-BlockCanary淺析

  1. 上線之後發現效能有所下降,替換方案。

    開一個監控執行緒,每隔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 雖然是後臺元件,不過它們生命週期也是佔用主執行緒的,呼叫的過於頻繁也會導致卡頓.

最後,給自己公眾號打個廣告,【碼農的嘮叨】聊技術,聊熱文,聊網際網路趣事,也發嘮叨

qrcode_for_gh_5febf245550e_258

相關文章