使用Systrace分析UI性能
- 原文鏈接 : Analyzing UI Performance with Systrace
- 原文作者 : Android Developers
- 譯文出自 : 開發技術前線 www.devtf.cn。未經允許,不得轉載!
- 譯者 : desmond1121
- 校對者: desmond1121
開發應用的時候,應該檢查它是否有流暢的用戶體驗,即60fps的幀率。如果由於某種原因丟幀,我們首先要做的就是知道系統在做什麼(造成丟幀的原因)。
Systrace允許你監視和跟蹤Android系統的行爲(trace)。它會告訴你係統都在哪些工作上花費時間、CPU週期都用在哪裏,甚至你可以看到每個線程、進程在指定時間內都在幹嘛。它同時還會突出觀測到的問題,從垃圾回收到渲染內容都可能是問題對象,甚至提供給你建議的解決方案。本文章將介紹如何導出trace以及使用它來優化UI的辦法。
總覽
Systrace可以幫助你分析應用在不同Android系統上的運行情況。它將系統和應用的線程運行情況放置在同一條時間線上分析。你首先需要收集系統和應用的trace(後面會告訴你怎麼做),之後Systrace會幫你生成一份細緻、直觀的報告,它展示了設備在你監測的這段時間內所發生的事情。
圖1. 連續滑動應用5秒的Trace,它並沒有表現得很完美。
圖1展示了應用在滑動不流暢的時候生成的trace。默認縮放成全局顯示,你可以放大到自己所關注的地方。橫軸代表着時間線,事件記錄按照進程分組,同一個進程內按線程進行縱向拆分,每個線程記錄自己的工作。
在本例中,一共有三個組:Kernel, SurfaceFlinger, App,他們分別以包名爲標識。每個應用進程都會包含其中所有線程的記錄信號,你可以看到從InputEvent到RenderThread都有。
生成Trace
在獲取trace之前需要做一些啓動工作。首先,設備要求API>=16(Android 4.1),之後通過正常的Debug流程(開啓調試、連接工作環境、安裝App)連接設備。由於需要記錄磁盤活動和內核工作,你可能需要root權限。不過大部分時候你只要能夠正常Debug即可。
Systrace 可以通過命令行或者圖形界面啓動,本篇文章重點介紹通過命令行使用Systrace。
在Android 4.3及以上的系統中獲取trace
在4.3以上的系統獲取Trace步驟:
- 保證設備USB連接正常,並可以debug;
- 在命令行中設置選項,開啓trace,比如:
$ cd android-sdk/platform-tools/systrace
$ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
- 在設備上做任何你想讓trace記錄的操作。
你可以通過Systrace選項來了解更多命令行選項。
在Android 4.2及以下的系統中獲取trace
在4.2及以下的系統中高效地使用Systrace的話,你需要在配置的時候顯式指定要trace的進程種類。一共有這兩類種類:
- 普通系統進程,比如圖形、聲音、輸入等。(通過tags設置,具體在Systrace命令行中有介紹)
- 底層系統進程,比如CPU、內核、文件系統活動。(通過options設置,具體在Systrace命令行中有介紹)
你可以通過以下命令行操作來設置tags:
- 使用
--set-tags
選項:
$ cd android-sdk/platform-tools/systrace
$ python systrace.py --set-tags=gfx,view,wm
- 重啓adb shell來trace這些進程:
$ adb shell stop
$ adb shell start
你也可以通過手機上的圖形界面設置tags:
- 在設備上進入設置> 開發者選項 > 監控 > 啓用跟蹤(部分手機上沒有這個選項);
- 選擇追蹤進程類型,點擊確認。
注意: 在圖形界面中設置tag時adb shell不用重新啓動。
在配置完tags後,你可以開始收集操作信息了。
如何在當前設置下啓動trace:
- 保證設備的usb連接正常,並且可以正常debug;
- 使用低系統等級的命令行選項開啓trace,比如:
$ python systrace.py --cpu-freq --cpu-load --time=10 -o mytracefile.html
- 在設備上做任何你想讓trace記錄的操作。
你可以通過Systrace選項來了解更多命令行選項。
分析trace報告
在你獲取trace之後你可以在網頁瀏覽器中打開它。這部分內容告訴你怎麼通過trace去分析和解決UI性能。
監視幀數
每個應用都有一行專門顯示frame,每一幀就顯示爲一個綠色的圓圈。不過也有例外,當顯示爲黃色或者紅色的時候,它的渲染時間超過了16.6ms(即達不到60fps的水準)。'w'鍵可以放大,看看這一幀的渲染過程中系統到底做了什麼。
提示:你可以按右上角的'?'按鈕來查看界面使用幫助。
單擊該幀可以高亮它,這時候跟該幀有關的內容會被突出顯示。在5.0及以上的系統中,顯示工作被拆分成UI線程和Render線程兩部分;在5.0以下的系統中,所有的顯示工作在UI線程中執行。
點擊單個Frame下面的組件可以看他們所花費的時間。每個事件(比如performTraversals
)都會在你選中的時候顯示出它們調用了哪些方法及所用的時間。
調查警告事件
Systrace會自動分析事件,它會將任何它認爲性能有問題的東西都高亮警告,並提示你要怎麼去優化。
圖3. 選擇一個被高亮幀,它會顯示出檢測到的問題(回收ListView消耗時間太長)。
在你選擇類似圖三中的問題幀之後,它就會提示你檢測出的問題。在這個例子中,它被警告的主要原因是ListView的回收和重新綁定花費太多時間。在Systrace中也會提供一些對應鏈接,它們會提供更多解釋。
如果你想知道UI線程怎麼會花費這麼多時間的話,你可以使用TraceView,它會告訴你都是哪些函數在消耗時間。
你可以通過右側的'Alert'選項卡來查看整個trace過程中發生的所有問題,並進行快速定位。
你可以將Alert面板中的問題視爲需要處理的bug,很有可能每一次微小的優化能夠去除整個應用中的警告!
應用級別調試
Systrace並不會追蹤應用的所有工作,所以你可以在有需求的情況下自己添加要追蹤的代碼部分。在Android 4.3及以上的代碼中,你可以通過Trace
類來實現這個功能。它能夠讓你在任何時候跟蹤應用的一舉一動。在你獲取trace的過程中,Trace.beginSection()
與Trace.endSection()
之間代碼工作會一直被追蹤。
下面這部分代碼展示了使用Trace
的例子,在整個方法中含有兩個Trace塊。
public void ProcessPeople() {
Trace.beginSection("ProcessPeople");
try {
Trace.beginSection("Processing Jane");
try {
// 待追蹤的代碼
} finally {
Trace.endSection(); // 結束 "Processing Jane"
}
Trace.beginSection("Processing John");
try {
// 待追蹤的代碼
} finally {
Trace.endSection(); // 結束 "Processing John"
}
} finally {
Trace.endSection(); // 結束 "ProcessPeople"
}
}
注意:在Trace是被嵌套在另一個Trace中的時候,
endSection()
方法只會結束理它最近的一個beginSection(String)
。即在一個Trace的過程中是無法中斷其他Trace的。所以你要保證endSection()
與beginSection(String)
調用次數匹配。注意:Trace的begin與end必須在同一線程之中執行!
當你使用應用級別追蹤的時候,你必須通過-a
或者-app=
來顯式地指定應用包名。可以通過Systrace指南查看更多關於它的信息。
你在評估應用的時候應該開啓應用級別跟蹤,即使當你沒有手動添加Trace
信號。因爲很多庫函數裏面是有添加Trace信號的(比如RecyclerView
),它們往往能夠提供很多信息。