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
- 查看类别:其他命令查看链接
遇到缺少win32con, pip install -i https://pypi.douban.com/simple pypiwin32python 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
Show Quick Setting tile
System Tracing
Trace saved
Share Trace
生成html文件 -
DDMS
Capture system wide trace using Android systrace
启动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: 高级选项 具体内容看图
-
- 左边呈现是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。
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"); }
-
-
源码性能调试
待定
网友评论