Google 鏈接
Systrace是一個platform-provided工具,用於記錄設備在短時間內的活動。 允許在系統級別上收集和檢查設備上運行的所有進程的時間信息。將來自Android內核的數據(如CPU調度程序、磁盤活動和應用程序線程)結合起來生成一個HTML報告,幫助確定如何最好地提高應用程序或遊戲的性能。該報告突出了它觀察到的問題(如在顯示動作或動畫時的ui jank),並且提供了有關如何修復這些問題的建議。但是,Systrace不會在應用程序進程中收集有關代碼執行的信息。有關應用正在執行的方法以及使用多少CPU資源的詳細信息使用Android Studio CPU Profiler,你也可以生成trace logs後使用Profiler查看。
三種使用方式:命令行調用,System Tracing APP,DDMS
在Android5.0(API級別21)或更高版本的設備上,渲染一個frame的工作被UI Thread和Render Thread拆分。在以前的版本上,創建一個frame的所有工作都是在UI thread上完成的。
在解決應用程序中與性能相關的錯誤(如啓動緩慢、轉換緩慢或UI jank)時,記錄跟蹤尤其有用。
-
命令行調用
Systrace command在android sdk tools包中提供,位於android-sdk/platform-tools/systrace/
啓動systrace,通過以下步驟:- 下載安裝Android Studio,然後下載SDK並更新。
不一定要使用Android Studio,但是現在的SDK只能通過Android Studio更新。 - 安裝python並將其包含在工作站的執行路徑中。添加path D:\Python27,cmd 中輸入python ,有信息
- python 2.7.9以後的自帶pip,添加path D:\Python27\Scripts,cmd 中輸入pip,有信息
- 通過USB調試連接到一個Android 4.3(API)或者 4.3以上的設備。
- 生成mynewtrace.html的文件; 當前目錄: D:\adt\SDK\platform-tools\systrace
python systrace.py -o mynewtrace.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res
- 查看類別:其他命令查看鏈接
python systrace.py --list-categories
win32con
需要啓動模擬器或者連接設備
- 下載安裝Android Studio,然後下載SDK並更新。
-
System Tracing APP
在Android 9.0(API級別28)或更高版本的設備上,可以使用 System Tracing的 System App在設備上記錄系統跟蹤。系統跟蹤將設備的活動保存到滾動緩衝區,該緩衝區可保存10-30秒的事件值。- 開啓開發者選項
- 打開開發者選項,選擇System Tracing;開啓Show Quick Setting tile的Switch Button。
- 或者,選擇要跟蹤的系統和傳感器調用的類別,並選擇緩衝區大小(以KB爲單位)。選擇與正在測試的用例相對應的類別,例如用於測試藍牙操作的音頻類別。
- 打開快速設置面板中的System Tracing 如下圖System Tracing,或者打開開發者選項中的System Tracing並開啓Record trace的Switch Button。
- 通知面板會出現一個System Tracing通知,點擊通知面板或者快速設置面板中的System Tracing,停止tracing
- 系統將顯示一個“saving trace”的新通知。保存完成後,系統將取消通知並顯示第三個通知,System Tracing已保存,並且已準備好分享你的trace。
- 點擊通知,顯示分享對話框,點擊share可以通過郵箱分享
- adb 命令下載,下載文件是.ctrace
cd /path-to-traces-on-my-dev-machine adb pull /data/local/traces/ .
- 生成html文件;當前目錄: D:\adt\SDK\platform-tools\systrace
cd /path-to-traces-on-my-dev-machine python systrace.py --from-file trace-file-name.ctrace
Developer Options
Show Quick Setting tile
System Tracing
Trace saved
Share Trace
生成html文件
-
DDMS
啓動DDMS後,點擊Capture system wide trace using Android systrace按鈕後點擊OK。
Destination File: 生成文件存放哪裏;
Trace duration (seconds): 追蹤週期時間
Trace Buffer Size(kb): 追蹤緩衝區大小
Enable Application Traces from: 選擇需要追蹤的進程
Commonly Used Tags: 常用標籤 具體內容看圖
Advanced Options: 高級選項 具體內容看圖Capture system wide trace using Android systrace
-
- 左邊呈現是UI Frames的每個進程,選擇你要觀察的APP,右邊是沿時間線指示呈現每個Frame。
綠色圓表示: 16.6毫秒內渲染完成的Frames。
黃色或紅色圓表示: 渲染時間超過16.6毫秒的Frames。 - 單擊一個frame 圓將高亮顯示它,並提供系統渲染該frame所做的相關信息包括系統在呈現該幀時正在執行的方法(因此可以調查這些導致ui-jank的方法)和Alert。 Alert指出主要問題是在ListView回收和重新綁定中花費太多時間。Alert中有相關事件的鏈接,這些鏈接可以更詳細地解釋系統在這段時間內所做的工作。如圖Android System Trace A Frame
- 若要查看每個Alert,以及觸發每個Alert的次數,請單擊窗口右側的Alerts選項卡,如圖Android System Trace Alert 所示。Alerts panel中查看跟蹤出現的問題,以及它們對jank的影響頻率。將Alerts panel視爲要修復的錯誤列表。通常,一個領域的微小變化或改進可以消除應用中的整個Alerts。
- 如果UI Thread做了太多的工作,需要找出哪些方法佔用了太多的CPU時間:
爲導致這些瓶頸的方法添加自定義事件,查看這些函數調用次數在Systrace中(具體操作下一段定義自定義事件)。
如果不確定哪些方法會導致UI Thread出現瓶頸,請使用Android Studio Cpu Profiler,。
- 左邊呈現是UI Frames的每個進程,選擇你要觀察的APP,右邊是沿時間線指示呈現每個Frame。
Capture system wide trace using Android systrace
Android System Trace
Android System Trace Zoom
Android System Trace A Frame
Android System Trace Alert
- 定義自定義事件
-
在Android 4.3(API級別18)及更高版本中,使用代碼中的Trace類在HTML報告中標記執行事件。需要使用-a或--app命令行選項運行Systrace,並指定應用程序的包名稱。
python systrace.py -a com.lqr.wechat -b 16384 -o my_systrace_report.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res
下面的代碼示例演示如何使用Trace類來標記方法的執行,包括該方法中的兩個嵌套代碼塊;多次調用BeginAtomon(String)時,調用EndSection()只結束最近調用的BeginAtomon(String)方法。因此,對於嵌套調用(如下面示例中的調用),需要確保每個對BeginAtomion()的調用都與對EndSection()的調用正確匹配。此外,不能在一個線程上調用BeginAtomon()並從另一個線程結束它,必須從同一個線程調用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 { // In 'try...catch' statements, always call `[endSection()](https://developer.android.google.cn/reference/android/os/Trace.html#endSection())` // in a 'finally' block to ensure it is invoked even when an exception // is thrown. 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); dataset.add(rowItem); } finally { Trace.endSection(); } holder.bind(dataset.get(position)); } finally { Trace.endSection(); } } ... }
-
Android 6.0(API級別23)及更高版本支持調用native層tracing
API 通過引入trace.h,將trace事件寫入系統緩衝區,然後使用Systrace進行分析。Android 6.0到4.3可以嘗試通過JNI調用。- 爲ATrace functions定義方法指針
#include <android/trace.h> #include <dlfcn.h> void *(*ATrace_beginSection) (const char* sectionName); void *(*ATrace_endSection) (void); typedef void *(*fp_ATrace_beginSection) (const char* sectionName); typedef void *(*fp_ATrace_endSection) (void);
- 在運行時加載ATrace符號,通常在對象構造函數中執行這個過程,出於安全原因,僅在應用程序或遊戲的調試版本中包含對dlopen()的調用。
// Retrieve a handle to libandroid. void *lib = dlopen("libandroid.so", RTLD_NOW || RTLD_LOCAL); // Access the native tracing functions. if (lib != NULL) { // Use dlsym() to prevent crashes on devices running Android 5.1 // (API level 22) or lower. ATrace_beginSection = reinterpret_cast<fp_ATrace_beginSection>(dlsym(lib, "ATrace_beginSection")); ATrace_endSEction = reinterpret_cast<fp_ATrace_endSection>(dlsym(lib, "ATrace_endSection")); }
- 在自定義事件的開始和結束調用atrace_begindomon() 和atrace_endsection()
#include <android/trace.h> char *customEventName = new char[32]; sprintf(customEventName, "User tapped %s button", buttonName); ATrace_beginSection(customEventName); // Your app or game's response to the button being pressed. ATrace_endSection();
- 跟蹤整個方法
當檢測調用堆棧或函數計時時,會發現跟蹤整個函數很有用。使用ATRACE_CALL()
宏使這種類型的跟蹤更容易設置。此外,通過創建try-catch
塊,這種宏允許跳過被跟蹤函數引發的異常或提前調用return
的情況。- 定義宏
#define ATRACE_NAME(name) ScopedTrace ___tracer(name) // ATRACE_CALL is an ATRACE_NAME that uses the current function name. #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) class ScopedTrace { public: inline ScopedTrace(const char *name) { ATrace_beginSection(name); } inline ~ScopedTrace() { ATrace_endSection(); } };
- 調用宏在被跟蹤方法中
void myExpensiveFunction() { ATRACE_CALL(); // Code that you want to trace. }
- 定義宏
- 給你的線程名稱
給事件發生的每個線程提供名稱,可以更容易地識別屬於特定操作的線程。#include <pthread.h> static void *render_scene(void *parm) { // Code for preparing your app or game's visual components. } static void *load_main_menu(void *parm) { // Code that executes your app or game's main logic. } void init_threads() { pthread_t render_thread, main_thread; pthread_create(&render_thread, NULL, render_scene, NULL); pthread_create(&main_thread, NULL, load_main_menu, NULL); pthread_setname_np(render_thread, "MyRenderer"); pthread_setname_np(main_thread, "MyMainMenu"); }
-
- 源碼性能調試
待定