App優化 Systrace


簡介

trace [tres] vt.跟蹤,追蹤; 追溯,探索; 探索; 查找;   n.痕跡; 痕跡,蹤跡; 微量,極少量;

Systrace是Android4.1中新增的性能數據采樣和分析工具,它可幫助開發者收集Android關鍵子系統(如SurfaceFlinger、WindowManagerService等Framework部分關鍵模塊、服務、View系統等)的運行信息,從而幫助開發者更直觀的分析系統瓶頸,改進性能。

Systrace允許你 監視和跟蹤Android系統的行為,它會告訴你 系統都在哪些工作上花費時間、CPU周期都用在哪里,甚至你 可以看到每個線程、進程在指定時間內都在干嘛。它同時還會 突出觀測到的問題,從垃圾回收到渲染內容都可能是問題對象,甚至 提供給你建議的解決方案

Systrace的功能包括 跟蹤系統的I/O操作、內核工作隊列、CPU負載以及Android各個子系統的運行狀況等。在Android平台中,它主要由3部分組成:
  • 內核部分:Systrace利用了Linux Kernel中的ftrace功能,所以,如果要使用Systrace的話,必須開啟kernel中和ftrace相關的模塊。
  • 數據采集部分:Android定義了一個Trace類,應用程序可利用該類把統計信息輸出給ftrace。同時,Android還有一個atrace程序,它可以從ftrace中讀取統計信息然后交給數據分析工具來處理。
  • 數據分析工具:Android提供一個systrace.py(python腳本文件,位於Android SDK目錄/tools/systrace中,其內部將調用atrace程序)用來配置數據采集的方式(如采集數據的標簽、輸出文件名等)和收集ftrace統計數據並生成一個結果網頁文件供用戶查看。從本質上說,Systrace是對Linux Kernel中ftrace的封裝。應用進程需要利用Android提供的Trace類來使用Systrace。

啟動Systrace

Systrace是Android4.1中新增的,所以 要求要生成Trace的手機在Android 4.1以上。
Systrace工具可以在sdk/platform-tools/ 中找,源碼位於external/chromium-trace下面。

Systrace可以通過命令行,Eclipse,Android Studio等方式啟動。
【Using  Android Studio】
  • 1.In Android Studio, open an Android application project. 1.Open the Device Monitor by selecting Tools > Android > Monitor.
  • 2.In the Devices tab, select the device on which to run a trace. If no devices are listed, make sure your device is connected via USB cable and that debugging is enabled on the device.
  • 3.Click the Systrace icon at the top of the Devices panel to configure tracing.
  • 4.Set the tracing options and click OK to start the trace.

【Using Eclipse】
  • 1.In Eclipse, open an Android application project. 1.Switch to the DDMS perspective, by selecting Window > Perspectives > DDMS.
  • 2.In the Devices tab, select the device on which to run a trace. If no devices are listed, make sure your device is connected via USB cable and that debugging is enabled on the device.
  • 3.Click the Systrace icon at the top of the Devices panel to configure tracing.
  • 4.Set the tracing options and click OK to start the trace.

【Using Device Monitor】
  • 1.Navigate to your SDK tools/ directory. 1.Run the monitor program.
  • 2.In the Devices tab, select the device on which to run a trace. If no devices are listed, make sure your device is connected via USB cable and that debugging is enabled on the device.
  • 3.Click the Systrace icon at the top of the Devices panel to configure tracing.
  • 4.Set the tracing options and click OK to start the trace.

生成Trace分析文檔

生成Trace分析文檔的步驟如下:
  • 打開手機調試模式,連接手機,運行APP
  • 啟動Systrace
  • 手機准備好你要進行抓取的界面
  • 配置文件路徑、抓取時間等
  • 點擊確定后開始操作手機,在時間到了后會自動生成報表(這個文件至少也有好幾兆)
  • 使用Chrome(其他瀏覽器很可能打不開)將這個文件打開進行分析

Systrace的一些配置
  • duration:抓取時間,通常設置5秒,並在5秒內重現問題,時間太短會導致問題重現時沒有被抓到,時間太長會導致JavaHeap不夠而無法保存。因此在能抓到問題點的情況下,時間越小越好。
  • Buffer Size:存儲Systrace的size,同樣太小會導致信息丟失,太長會導致Java Heap不夠而無法保存,建議【20480】。如果檢測結果有異常,請調整Buffer Size的大小試試。
  • Application:檢測的應用,默認選擇none
  • Commonly Used Tag:常用標簽,這部分TAG全部使能上。只關注顯示情況的話 ,只選取Graphics和View System就可以。
  • Advanced Options:高級選項。如果設備root了,可以看到更多的TAG,如eMMC commands/ Synchonization/Kernel Workqueues。

測試時發現,5.1的華為手機點擊確定后報以下誤:
Unexpected error while collecting system trace.
Unable to find trace start marker 'TRACE:':error opening /sys/kernel/debug/tracing/options/overwrite: No such file or directory
而7.0的三星手機正常

打開Trace文檔

可以用 Chrome瀏覽器打開生成的trace文件。 瀏覽時可以使用w/s/a/d快捷鍵來放大、縮小、移動等操作。 可以點擊右上角的?號來查看等多的操作。
Key Description
w Zoom into the trace timeline.
s Zoom out of the trace timeline.
a Pan left on the trace timeline.
d Pan right on the trace timeline.
e Center the trace timeline on the current mouse location.
g Show grid at the start of the currently selected task.
Shift+g Show grid at the end of the currently selected task.
Right Arrow Select the next event on the currently selected timeline.
Left Arrow Select the previous event on the currently selected timeline.
雙擊
Zoom into the trace timeline.
Shift+雙擊 Zoom out of the trace timeline.

分析Trace文檔--簡介

縱軸代表着時間線,事件記錄按照進程分組,同一個進程內按線程進行縱向拆分,每個線程記錄自己的工作,可收縮/展開。

在本例中,一共有三個組:Kernel, SurfaceFlinger, App,他們分別以 包名為標識。 每個應用進程都會包含其中 所有線程的記錄信號,你可以看到從InputEvent到RenderThread都有。
除了進程和線程運行信息,還有兩個重要信息:
【Frame】
在每個app進程,都有一個Frames行,正常情況以綠色的圓點表示。當圓點顏色為黃色或者紅色時,意味着這一幀超過16.6ms(即發現丟幀),這時需要通過放大那一幀進一步分析問題。對於Android 5.0(API level 21)或者更高的設備,該問題主要聚焦在UI Thread和Render Thread這兩個線程當中。對於更早的版本,則所有工作在UI Thread。

【Alerts】
Systrace能自動分析trace中的事件,並能自動高亮性能問題作為一個Alerts,建議調試人員下一步該怎么做。
比如對於丟幀時,點擊黃色或紅色的Frames圓點便會有相關的提示信息;另外,在systrace的最右側,有一個Alerts tab可以展開,這里記錄着所有的的警告提示信息。
當我們點擊了Alerts或者點擊右邊的Alerts列表中的任何一點,我們可以看到,在界面的最底部,會有相對應的優化提示,以及可能會出現優化的視頻教程鏈接。

比如上面的提示說你View的draw繪制花的時間太長了,然后我們可以根據Description來很明白的看到提示的內容是什么。

然后我們可以點擊一塊Frames中的F來查看,同樣的它會生成一份跟Alerts類似的報告結果並放在界面的最低端。
我們可以通過按下m鍵查看這一幀到下一幀所花費的時間以及哪個方法被調用的最長。
可以明顯看到這時間> 16.6ms,大於系統要求UI的 60fps水准所以系統會報出黃色的警告。
照樣我們從Description中可以讀出到底是哪里出了問題
Description :ListView item recycling involved inflating views. Ensure your Adapter#getView() recycles the incoming View, instead of constructing a new one.
//ListView項目回收涉及inflating視圖。 確保您的Adapter#getView() 循環使用傳入的View,而不是構建新的View。
根據系統提示,我們就能順着這條路去找界面的代碼哪里出現了不足從而優化完善。

當然Systrace 無法幫你定位到代碼里面的具體到某一行代碼,但是我們可以通過Alerts和Frames來能基本上優化了不足的地方,然后我們可以根據 TraceView來分析具體函數花了多長時間來進一步優化代碼提高性能。

分析Trace文檔--案例

上面介紹了Systrace中不同區域的功能,當然最有趣的還是 Alerts和Frames 兩欄,讓我們來選擇最上方的Alerts瞧瞧:
這個警告指出了,有一個View#draw()方法執行了比較長的時間。我們可以在下面看到問題的描述、鏈接,甚至是相關的視頻。
下面我們看Frames這一行,可以看到這里展示了被繪制出來的每一幀,並且用綠、黃、紅三顏色來區分它們在繪制時的性能。我們選一個紅色幀來瞅瞅:
在最下方,我們看到了與這一幀所相關的一些警告。
在這三個警告中,有一個是我們上面所提到的(View#draw())。接下來我們在這一幀處放大並在下方展開“Inflation during ListView recycling”這條警告:
我們可以看到警告部分的總耗時32毫秒,遠高於了我們對保障60fps所需的16.6毫秒繪制時間。 同時還有更多的ListView每個條目的繪制時間,大約是6毫秒每個條目,總共五個。而Description描述項中的內容會幫助我們理解問題,甚至提供問題的解決方案。回到我們上一張圖片,我們可以在“inflate”這一個塊區處放大,並且觀察到底是哪些View在被填充過程中耗時比較嚴重。

下面是另外一個渲染過慢的實例:
在選擇了某一幀之后,我們可以按“m”鍵來高亮這一幀,並且在上方看到了這一部分的耗時,如圖,我們看到了這一陣的繪制總共耗時大約19毫秒。而當我們展開這一幀唯一的一個警告時,我們發現了“Scheduling delay”這條錯誤。
Scheduling delay(調度延遲)的意思就是一個線程在處理一塊運算的時候,在很長一段時間都沒有被分配到CPU上面做運算,從而導致這個線程在很長一段時間都沒有完成工作。我們選擇這一幀中最長的一塊,從而得到更加詳細的信息:

在紅框區域內,我們看到了“Wall duration”,他代表着這一區塊的開始到結束的耗時。之所以叫作“Wall duration”,是因為他就像是牆上的一個時鍾,從線程的一開始就為你計時。
而CPU Duration一項中顯示了實際CPU在處理這一區塊所消耗的時間。
很顯然,兩個時間的差距還是非常大的。整個區塊耗時18毫秒,而在這之中CPU只消耗了4毫秒的時間去運算。這就有點奇怪了,所以我們應該看一下在這整個過程之中,CPU去干嗎了。
可以看到,所有四個線程都非常的繁忙。
選擇其中的一個線程會告訴我們是哪個程序在占用他,在這里是一個包名為com.udinic.keepbusyapp的程序。在這里,由於另外一個程序占用CPU,導致了我們的程序未能獲得足夠的CPU資源。
但是這種情況其實是暫時的,因為被其他后台應用占用CPU的情況並不多見,但仍有其他應用的線程或是主線程占用CPU。而Systrace也只能為我們提供一個概覽,他的深度是有限的。所以要找到我們app中到底是什么讓我們的CPU繁忙,我們還要借助另一個工具——Traceview。

通過Trace類跟蹤應用案例

Trace類能夠讓你在任何時候跟蹤應用的一舉一動。在你獲取trace的過程中,Trace.beginSection()與Trace.endSection()之間代碼工作會一直被追蹤。
比如,我們在recyclerview的bindview中使用sleep模擬耗時操作,滾動時會出現明顯卡頓
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onBindViewHolder(StaggredAdapter.MyHolder holder, int position) {
    holder.mivItem.setImageResource(mlstPics.get(position));

    Trace.beginSection("aaa");//生成的trace文件中,會在跟蹤的代碼段執行對應時間軸區間打上一個tag標記
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Trace.endSection();//Trace的begin與end必須在同一線程之中執行
}

使用systrace跟蹤,生成如下分析圖
找到分析進程對應的ui線程,線程的縱向信息記錄的是調用關系,橫向信息記錄的是調用順序,代碼中的標記“aaa”標記了sleep的時間段,可以按m鍵高亮顯示這個標記對應的時間段,可以看出以下信息:
  • 丟幀,在aaa標記時段的前面,有一幀標紅的frame,它跟下一個frame之間間隔事件很長(代碼sleep中)
  • 調用關系,RV滾動 ---> bindview ---> aaa(sleep)

2017-10-20





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM