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列表中,定位到當前應用的包名所在的程序項,展開後包含deliverInputEvent
, UI Thread
, RenderThread
三個子項。我們重點分析這部分內容。
右側有一行寫有F的圈圈,表示每個Frame的綜合評價。如果是綠色,表示這一幀的渲染是ok的。如果是紅色或者黃色,表示渲染超時了。 點選這個F圓圈,在下部的視窗中會展示一些詳細資訊。如果這一幀的渲染沒有任何問題,下面的內容是空的;如果這一幀有問題,會展示Alert資訊(我們稍後詳細討論Alert)。
圖:Systrace的介面概覽和F標記
圖:觀察有效能問題的Frame的提示資訊
點選其中的一個方塊,可以使這一段耗時高亮,在下面會展示出詳細的耗時資訊。
圖:選中的Slice的詳細耗時資訊
舉例:一個Frame的耗時資訊詳解
一幀的繪製大概需要經過這樣幾個區間(縱向的灰色豎條表示的是Vsync的時間)。
- Choreographer#doFrame (UI Thread)
- traversal
- measure(如果measure了多次,會在trace中有體現)
- layout
- draw
- traversal
- DrawFrame (RenderThread)
- syncFrameState
- uploadTexture
- flushDrawingCommands
- eglSwapBuffersWithDamageKHR
- syncFrameState
圖:一幀的耗時
分析Alert的資訊
Systrace會對trace中的一些事件執行自動分析,然後將一些效能問題以Alert形式標出,並給出一定的建議。前面已經提到,在有效能問題的Frame上點選,會在下方的詳情中展示Alert,點選Alert項,會給出詳細的耗時資訊、相關描述,有的還會給出連結,鏈到指定的trace塊中。
另外,右側有一個Alert的tab頁,會把此次trace中所有的Alert資訊列舉出來。點選其中一個Alert,對應的F圈會高亮,從而可以定位到有問題效能的幀。
發生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()
結束最近的一次追蹤。
下面是官方說明裡面摘抄的一段示例程式碼:
-
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
-
@Override
-
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-
Trace.beginSection("MyAdapter.onCreateViewHolder");
-
MyViewHolder myViewHolder;
-
try {
-
myViewHolder = MyViewHolder.newInstance(parent);
-
} finally {
-
Trace.endSection();
-
}
-
return myViewHolder;
-
}
-
@Override
-
public void onBindViewHolder(MyViewHolder holder, int position) {
-
Trace.beginSection("MyAdapter.onBindViewHolder");
-
try {
-
try {
-
Trace.beginSection("MyAdapter.queryDatabase");
-
RowItem rowItem = queryDatabase(position);
-
mDataset.add(rowItem);
-
} finally {
-
Trace.endSection();
-
}
-
holder.bind(mDataset.get(position));
-
} finally {
-
Trace.endSection();
-
}
-
}
-
}
新增之後,我們就可以在抓到的trace中看到對應的耗時,非常方便。