1. 程式人生 > >Android Systrace的使用和分析

Android Systrace的使用和分析

Systrace的使用和分析

概述

Systrace是分析Android效能問題的神器,Google IO 2017上更是對其各種強推。Systrace其實和TraceView很像,都是統計一些方法(或者是一個執行階段)的耗時,然後在一個有時間軸的圖表上展示出來。不同的是,TraceView是收集所有方法的耗時資訊和巢狀關係,這使得TraceView本身的效能消耗很大,反而影響了實際的執行環境。Systrace則採用了不同的思路,通過有限的Label先粗略統計出一個階段的耗時,定位到問題以後,在慢慢細化和進一步測算分析。

摘抄一段Systrace的原理描述:

在介紹使用之前,先簡單說明一下Systrace的原理:它的思想很樸素,在系統的一些關鍵鏈路(比如System Service,虛擬機器,Binder驅動)插入一些資訊(我這裡稱之為Label),通過Label的開始和結束來確定某個核心過程的執行時間,然後把這些Label資訊收集起來得到系統關鍵路徑的執行時間資訊,進而得到整個系統的執行效能資訊。Android Framework裡面一些重要的模組都插入了Label資訊(Java層的通過android.os.Trace類完成,native層通過ATrace巨集完成),使用者App中可以新增自定義的Label,這樣就組成了一個完成的效能分析系統。

另一方面,系統的渲染的關鍵步驟都有framework預置的label,Systrace又提供了非常適合觀察系統的UI效能/流暢度的功能,所以Systrace也是分析UI效能的神器。

使用

環境條件

  • Android SDK Tools 20
  • 安裝的python並添加了環境變數
  • Android 4.1以上的手機

啟動trace並記錄

可以使用DDMS進行記錄:

  • Tools -> Android -> Android Device Monitor
  • 選擇app,點選Systrace按鈕
  • 設定儲存的檔案路徑、監控的時間、監控的內容等,開始記錄

結果的展現

不論是DDMS還是命令列,最終都會儲存一個html檔案,用chrome瀏覽器開啟,即可進行分析。

常用標籤

不論是DDMS還是命令列,都可以在啟動trace前指定採集哪些系統預置的標籤。下面把一些常用的標籤類別列舉如下:

  • Graphics: Graphic系統的相關資訊,包括SerfaceFlinger,VSYNC訊息,Texture,RenderThread等;分析卡頓非常有效。
  • Input:
  • View System: View繪製系統的相關資訊,比如onMeasure,onLayout等;對分析卡頓比較有幫助。
  • Window Manager:
  • Activity Manager: ActivityManager呼叫的相關資訊;用來分析Activity的啟動過程比較有效。
  • Application
    :
  • Resource Loading:
  • Dalvik VM: 虛擬機器相關資訊,比如GC停頓等。
  • CPU Scheduling: CPU排程的資訊;你能看到CPU在每個時間段在執行什麼執行緒;執行緒排程情況,比如鎖資訊。

Systrace的分析

分析幀率

基本操作:

  • 'w'按鍵:放大
  • 's'按鍵:縮小
  • 'd'按鍵:向右平移
  • 'a'按鍵:向左平移

首先在左邊縱向的pid列表中,定位到當前應用的包名所在的程序項,展開後包含deliverInputEventUI ThreadRenderThread三個子項。我們重點分析這部分內容。

右側有一行寫有F的圈圈,表示每個Frame的綜合評價。如果是綠色,表示這一幀的渲染是ok的。如果是紅色或者黃色,表示渲染超時了。 點選這個F圓圈,在下部的視窗中會展示一些詳細資訊。如果這一幀的渲染沒有任何問題,下面的內容是空的;如果這一幀有問題,會展示Alert資訊(我們稍後詳細討論Alert)。

Systrace的介面概覽和F標記

圖:Systrace的介面概覽和F標記

觀察有效能問題的Frame的提示資訊

圖:觀察有效能問題的Frame的提示資訊

點選其中的一個方塊,可以使這一段耗時高亮,在下面會展示出詳細的耗時資訊。

詳細

圖:選中的Slice的詳細耗時資訊

舉例:一個Frame的耗時資訊詳解

一幀的繪製大概需要經過這樣幾個區間(縱向的灰色豎條表示的是Vsync的時間)。

  • Choreographer#doFrame (UI Thread)
    • traversal
      • measure(如果measure了多次,會在trace中有體現)
      • layout
      • draw
  • DrawFrame (RenderThread)
    • syncFrameState
      • uploadTexture
    • flushDrawingCommands
    • eglSwapBuffersWithDamageKHR

一幀的耗時

圖:一幀的耗時

分析Alert的資訊

Systrace會對trace中的一些事件執行自動分析,然後將一些效能問題以Alert形式標出,並給出一定的建議。前面已經提到,在有效能問題的Frame上點選,會在下方的詳情中展示Alert,點選Alert項,會給出詳細的耗時資訊、相關描述,有的還會給出連結,鏈到指定的trace塊中。

另外,右側有一個Alert的tab頁,會把此次trace中所有的Alert資訊列舉出來。點選其中一個Alert,對應的F圈會高亮,從而可以定位到有問題效能的幀。

Alerts tab

發生Alert之後,可能我們已有的資訊還不足以解決這些效能問題。此時,我們可以考慮先使用TraceView來定位耗時較長的方法,然後針對這些有問題的方法,在程式碼中新增Mark後,再執行Systrace進行確認和進一步的分析。(注意:TraceView本身有一定的效能損耗,會導致得出的結果和實際有較大出入,所以不建議使用TraceView取代Systrace,而是使用它作為查詢問題的一個輔助工具)。

下一節我們進一步介紹,如何在程式碼中新增Systrace的Mark。

舉例:一些Alert資訊

這裡列舉一些常見的Alert資訊:

  • Scheduling delay
  • Expensive measure/layout pass
  • Expensive Bitmap uploads
  • Inefficient ListView recycling/rebinding
  • Inflation during ListView recycling
  • Long View#draw()

從程式碼中追蹤效能問題

從Android 4.3(API 18)開始,使用Trace類,可以在程式碼中新增更加詳細的標記。使用Trace.beginSection(String)開始一段追蹤,使用Trace.endSection()結束最近的一次追蹤。

下面是官方說明裡面摘抄的一段示例程式碼:

  1. public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

  2. @Override

  3. public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

  4. Trace.beginSection("MyAdapter.onCreateViewHolder");

  5. MyViewHolder myViewHolder;

  6. try {

  7. myViewHolder = MyViewHolder.newInstance(parent);

  8. } finally {

  9. Trace.endSection();

  10. }

  11. return myViewHolder;

  12. }

  13. @Override

  14. public void onBindViewHolder(MyViewHolder holder, int position) {

  15. Trace.beginSection("MyAdapter.onBindViewHolder");

  16. try {

  17. try {

  18. Trace.beginSection("MyAdapter.queryDatabase");

  19. RowItem rowItem = queryDatabase(position);

  20. mDataset.add(rowItem);

  21. } finally {

  22. Trace.endSection();

  23. }

  24. holder.bind(mDataset.get(position));

  25. } finally {

  26. Trace.endSection();

  27. }

  28. }

  29. }

新增之後,我們就可以在抓到的trace中看到對應的耗時,非常方便。

新增自定義的mark

References