【工利其器】必會工具之(三)systrace篇(1)官網翻譯


前言

       Android 開發者官網中對systrace(Android System Trace)有專門的介紹,本篇文章作為systrace系列的開頭,筆者先不做任何介紹,僅僅翻譯一下官網的介紹。在后續的文章中再整理一份學習教程,以及筆者的實踐經歷。官網中對該工具的介紹文檔路徑為【https://developer.android.google.cn/studio/command-line/systrace?hl=en#java】。或者在進入到官網的首頁后,按照Android Developers > Android Studio > USER GUIDE > Command line tools > systrace的路徑訪問該文檔。

       該文檔主要包含如下內容:

 

一、systrace簡述

       systrace命令允許你收集和檢查在你的設備上運行的所有系統級別進程的定時信息。它聯合Android內核(比如CPU調度程序)、磁盤活動和app線程,生成一份HTML報告,如圖1所示:

  圖1:一個systrace的HTML報告案例,它顯示了與app 5秒鍾的交互。這份報告高亮顯示了那些systrace認為可能沒有被適當地渲染的幀。

       這份報告提供了一份在給定時間段內Android設備系統進程的全局圖。它也檢查了被捕獲的追蹤信息,用於高亮顯示它觀察到的問題,比如顯示動作或動畫時的UI jank(筆者注:界面來不及刷新導致的卡塞空白現象),以及提供修復這些問題的建議。但是,systrace不會收集在app進程內與代碼執行相關的信息。 關於你的app正在執行哪些方法以及它占用了多少CPU資源的詳情,請查看 【Android Studio CPU profiler】。你也可以使用CPU Profiler來生成追蹤日志,導出並檢查它們。

       這份文檔解釋了怎樣從命令行生成systrace報告,操作由工具生成的trace文件,並且使用它們分析及改善應用的UI性能。

★注意:在運行於Android 9(API level 28)或者更高的設備上,你可以使用一個叫做System Tracing的系統app在設備上記錄system trace。

      為了運行systrace,請完成下面的步驟:

      systrace工具在Android SDK Tools 包中提供,其路徑為 android-sdk/platform-tools/systrace/

 

二、語法

       為了給app生成HTML報告,你需要在命令行中使用如下的語法運行systrace:

$python systrace.py [option][categories]

       例如,如下的命令行調用了systrace用於記錄設備活動,並且生成一份名為 mynewtrace.html 的HTML報告。該categories列表對大多數設備而言是一個合理的默認列表。

$ python systrace.py -o mynewtrace.html sched freq idle am wm gfx view \ binder_driver hal dalvik camera input res
★ 提示:如果你想看輸出的trace中任務的名字,你的命令參數中必須包含“sched” category。

 想查看你連接的設備所支持的category列表,請運行下面的命令:

$ python systrace.py --list-categories

 如果你沒有指定任何的category或者option,systrace會生成一個包含所有可用category的報告並且使用默認的設置。這些可用的category依賴於你所連接的正在使用的設備。

  1、全局option

 

全局option 描述
-h | --help 顯示幫助信息
-l | --list-categories 列出你連接的設備所支持的可用category

  2、命令和命令選項

Commands and options Description
-o file 把HTML trace報告寫入到指定file。如果你不指定這個選項,systrace將會把你的報告保存到和systrace.py相同的根目錄下,並且命名為trace.html。
-t N | --time=N 追蹤設備活動N秒鍾。如果你不指定該選項,systrace將會提示你在命令行中按Enter鍵結束追蹤。
-b N | --buf-size=N 使用一個大小為N KB的trace緩存。這個選項可以讓你限制追蹤過程中收集的數據的大小。
-k functions
| --ktrace=functions
追蹤指定內核函數的活動,在一個以逗號隔開的列表中列出。
-a app-name
| --app=app-name

 激活追蹤app,這些app在以逗號分隔的進程名列表中被指定列出。這些app必須包含來自於Trace 類的追蹤檢測調用。

無論何時你profile你的應用,你都應該指明這個選項,很多庫(比如RecyclerView)都包含了追蹤檢測調用,

當你激活應用級別的追蹤時,這些調用提供了有用的信息。想了解更多信息,請閱讀關於怎樣“檢測你的app代碼”這部分內容。

--from-file=file-path 從文件當中創建一個交互式的HTML報告,比如包含原始trace數據的TXT文件,而不是運行實時追蹤。
-e device-serial
| --serial=device-serial
在指定連接的設備上進行追蹤,該設備由設備序列號來識別。
categories 包含你所指定的系統進程的追蹤信息,比如gfx表示用於圖像渲染的系統進程。你可以通過加上 -l 命令運行systrace來查看你所連接的設備上可用的服務列表。

 

三、調查用戶界面性能問題

       systrace 在檢查你的app的用戶界面性能方面尤其有用,因為它能夠分析你的代碼和幀率來驗證問題區域和建議可能的解決方案。首先,按照如下步驟進行:

      1)在你連接的設備上運行你的app。

      2)用下面的命令運行systrace,

$ python systrace.py -t 10 [other-options] [categories]

       這個例子會追蹤你的app 10秒鍾。

      3)當systrace正在運行的時候,和你的app進行交互(筆者注:即操作你的app)。

      4)在你定義的限定時間過去后,比如該例中的10秒,systrace會生成一個HTML 報告。

      5)使用一個web瀏覽器打開這份HTML報告。

       通過和這份報告交互,你可以檢查設備在這段記錄時間內的CPU使用情況。為了幫助操作HTML報告,請查看“鍵盤快捷鍵”這一部分,或者點擊報告右上角的"?"按鈕。

       下面這一部分解釋了怎樣檢查報告中的信息,從而找到並修復UI性能問題。

  1、檢查幀和警告

       如圖2所示,報告列出了每一個渲染UI幀的進程並且沿着時間線指出了所有的渲染幀。這些幀在16.6毫秒內渲染一幀, 需要維持一個穩定的每秒60幀的幀率,在報告中他們用綠色的圓圈表示。那些渲染超過16.6毫秒的幀則用黃色或者紅色圓圈表示。

圖2:長時間運行的幀放大后的systrace顯示

★ 注意:在運行版本為Android5.0(API level 21)或更高的設備上,UI線程和渲染線程之間用於渲染幀的工作是分離的。在之前的版本中,創建幀的所有工作都是在UI線程中完成的。

       點擊一個Frame圓圈(帶有F標記的圓圈,后面簡稱圓圈)會讓它變成高亮並且提供額外的信息,這些信息是關於系統渲染這一幀做所的工作,包括警告。同時也會向你顯示渲染這一幀過程中系統正在執行的方法,所以你可以調查引起那些UI jank的方法。

圖3:選擇有問題的幀,一個警告會出現在trace報告下面來標識問題。

       當你選擇一個渲染較慢的幀,你會在報告面板底部看到一個警告。圖3中顯示的警告喚起了該幀主要的問題,而該幀在ListView內回收和重新綁定時花費了太多時間。有一些鏈接指向trace中有關事件,他們解釋了更多關於這段時間內系統做了些什么。

       為了查看該工具在你的trace中發現的每一個警告,以及該設備觸發每一個警告的次數,請點擊窗口最右邊的“Alerts”標簽,如圖4所示。這個“Alerts”面板會幫你查看在這份trace中發生了什么問題,以及引起UI jank的頻率。把這個面板當成一個bug列表去修復。通常,一個在某區域微小的改變或者改善可能消除你app中整個警告類型。

圖4:點擊右側的“Alert”按鈕將顯示“alter”標簽

       如果你看到在UI線程中做了太多的工作,你需要找出是哪個方法消費了太多的CPU時間。有一種方法就是添加trace標記(查看“檢測你的app代碼”這一節)到那些你認為有可能導致這些瓶頸的方法中,用來查看那些在systrace中出現的功能調用。如果你不確定在UI線程中哪些方法可能導致瓶頸,使用Android Studio CPU profier 。你可以生成trace日志並且使用CPU Profiler來導入和檢測它們。  

  2、HTML報告鍵盤快捷鍵

     下面的表格列出了當瀏覽systrace HTML報告時可用的鍵盤快捷鍵。

按鍵 描述
W 放大trace時間軸。
S 縮小trace時間軸。
A 在時間軸上向左平移。
D 在時間軸上向右平移。
E 將trace時間軸置於當前鼠標的中心。
G 在當前選擇的任務的開始處顯示網格。
Shift + G 在當前選擇的任務的結尾處顯示網絡.
Right Arrow 在當前選擇的時間軸上選擇下一個事件(筆者注:當聚焦在frame 圓圈上時容易看到效果)。
Left Arrow 愛當前選擇的時間軸上選擇前一個事件。

 

四、檢測你的app代碼

       因為systrace僅僅只在系統級別給你顯示進程信息,所以在HTML報告中很難知道在給定的時間內你的app執行了哪些方法。在Android4.3(API level 18)已經更高的版本中,你可以在你的代碼中使用Trace類來標記HTML報告中執行的事件。你沒有必要用systrace去檢測你的代碼來記錄trace,但是這樣做可以幫助你看到你的app代碼中哪部分可能引起線程掛起或者UI jank。這種途徑有別於使用Debug類,Trace類簡單地添加標簽到systrace報告,但是Debug類通過.trace文件能幫助你檢測詳細的app CPU使用情況。

       為了生成包含你檢測trace事件的systrace HTML報告,你需要運行結合-a或者--app命令行運行systrace,並指明你的app的包名。

       下面的代碼實例向你展示了怎樣使用Trace類來標記方法的執行,包括在那個方法內的兩段嵌套的代碼塊:

 1 public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
 2     ...
 3     @Override
 4     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 5         Trace.beginSection("MyAdapter.onCreateViewHolder");
 6         MyViewHolder myViewHolder;
 7         try {
 8             myViewHolder = MyViewHolder.newInstance(parent);
 9         } finally {
10             // In 'try...catch' statements, always call endSection()
11             // in a 'finally' block to ensure it is invoked even when an exception
12             // is thrown.
13             Trace.endSection();
14         }
15         return myViewHolder;
16     }
17 
18    @Override
19     public void onBindViewHolder(MyViewHolder holder, int position) {
20         Trace.beginSection("MyAdapter.onBindViewHolder");
21         try {
22             try {
23                 Trace.beginSection("MyAdapter.queryDatabase");
24                 RowItem rowItem = queryDatabase(position);
25                 dataset.add(rowItem);
26             } finally {
27                 Trace.endSection();
28             }
29             holder.bind(dataset.get(position));
30         } finally {
31             Trace.endSection();
32         }
33     }
34 ...
35 }

 

★ 注意:當你調用beginSection(String)多次,調用endSection()只結束最近一次調用的beginSection(String)。所以,對於嵌套的代碼,比如上面例子中的,你需要確定你適當地匹配了一次beginSection()調用和一次endSection()。另外,你不能在一個線程中調用beginSection(),卻在另外一個線程中結束它,你必須在相同的線程中調用endSection()。

 

結語

       到這里,該篇文章就翻譯結束了,后面的文章中,筆者將根據自己的理解和實際操作,繼續對System Trace進行闡述。限於筆者的水平,如有翻譯不准確或不妥當的地方,望不吝賜教。


免責聲明!

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



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