使用Systrace分析UI性能

使用Systrace分析UI性能


開發應用的時候,應該檢查它是否有流暢的用戶體驗,即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步驟:

  1. 保證設備USB連接正常,並可以debug;
  2. 在命令行中設置選項,開啓trace,比如:
    $ cd android-sdk/platform-tools/systrace
    $ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
  1. 在設備上做任何你想讓trace記錄的操作。

你可以通過Systrace選項來了解更多命令行選項。

在Android 4.2及以下的系統中獲取trace

在4.2及以下的系統中高效地使用Systrace的話,你需要在配置的時候顯式指定要trace的進程種類。一共有這兩類種類:

  • 普通系統進程,比如圖形、聲音、輸入等。(通過tags設置,具體在Systrace命令行中有介紹)
  • 底層系統進程,比如CPU、內核、文件系統活動。(通過options設置,具體在Systrace命令行中有介紹)

你可以通過以下命令行操作來設置tags:

  1. 使用 --set-tags選項:
    $ cd android-sdk/platform-tools/systrace
    $ python systrace.py --set-tags=gfx,view,wm
  1. 重啓adb shell來trace這些進程:
    $ adb shell stop
    $ adb shell start

你也可以通過手機上的圖形界面設置tags:

  1. 在設備上進入設置> 開發者選項 > 監控 > 啓用跟蹤(部分手機上沒有這個選項);
  2. 選擇追蹤進程類型,點擊確認。

注意: 在圖形界面中設置tag時adb shell不用重新啓動。

在配置完tags後,你可以開始收集操作信息了。

如何在當前設置下啓動trace:

  1. 保證設備的usb連接正常,並且可以正常debug;
  2. 使用低系統等級的命令行選項開啓trace,比如: $ python systrace.py --cpu-freq --cpu-load --time=10 -o mytracefile.html
  3. 在設備上做任何你想讓trace記錄的操作。

你可以通過Systrace選項來了解更多命令行選項。

分析trace報告

在你獲取trace之後你可以在網頁瀏覽器中打開它。這部分內容告訴你怎麼通過trace去分析和解決UI性能。

監視幀數

每個應用都有一行專門顯示frame,每一幀就顯示爲一個綠色的圓圈。不過也有例外,當顯示爲黃色或者紅色的時候,它的渲染時間超過了16.6ms(即達不到60fps的水準)。'w'鍵可以放大,看看這一幀的渲染過程中系統到底做了什麼。

提示:你可以按右上角的'?'按鈕來查看界面使用幫助。

frame-unselected 圖2. Systrace顯示長渲染時間的幀

單擊該幀可以高亮它,這時候跟該幀有關的內容會被突出顯示。在5.0及以上的系統中,顯示工作被拆分成UI線程和Render線程兩部分;在5.0以下的系統中,所有的顯示工作在UI線程中執行。

點擊單個Frame下面的組件可以看他們所花費的時間。每個事件(比如performTraversals)都會在你選中的時候顯示出它們調用了哪些方法及所用的時間。

調查警告事件

Systrace會自動分析事件,它會將任何它認爲性能有問題的東西都高亮警告,並提示你要怎麼去優化。

frame-selected 圖3. 選擇一個被高亮幀,它會顯示出檢測到的問題(回收ListView消耗時間太長)。

在你選擇類似圖三中的問題幀之後,它就會提示你檢測出的問題。在這個例子中,它被警告的主要原因是ListView的回收和重新綁定花費太多時間。在Systrace中也會提供一些對應鏈接,它們會提供更多解釋。

如果你想知道UI線程怎麼會花費這麼多時間的話,你可以使用TraceView,它會告訴你都是哪些函數在消耗時間。

你可以通過右側的'Alert'選項卡來查看整個trace過程中發生的所有問題,並進行快速定位。

frame-selected-alert 圖4. 點擊Alert選項卡。

你可以將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),它們往往能夠提供很多信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章