原文地址:https://developer.android.com/studio/profile/systrace.html
在开发应用时,通常使用60fps的帧率来检测交互是否流畅,如果中途出错了,或者发生了掉帧,解决这个问题的第一步应当是搞清楚当前系统在做什么。
Systrace工具可以在程序运行的时候收集实时的信息,记录时间以及CPU的分配情况,记录每个线程和进程在任意时间的运行情况,可以自动分析出一些重要的原因,并且给出建议。
Systrace可以帮助你分析应用是如何设备上运行起来的,它将系统和应用程序线程集中在一个共同的时间轴上,分析systrace的第一步需要在程序运行的时间段中抓取trace log,在抓取到的trace文件中,包含了这段时间中你想要的关键信息,交互情况。
图1显示的是当一个app在滑动时出现了卡顿的现象,默认的界面下,横轴是时间,纵向为trace event,trace event 先按进程分组,然后再按线程分组.
从上到下的信息分别为Kernel,SurfaceFlinger,应用包名。通过配置trace的分类,可以根据配置情况记录每个应用程序的所有线程信息以及trace event的层次结构信息。
首先需要一些准备工作:
第一,android 4.1及以上的设备
第二,开启调试模式,安装你的应用
第三,某些trace信息需要root权限才能够获取,比如 disk activity和工作队列等,但是大部分都不需要root权限。
systrace的追踪有两种方式:一种是通过命令行(待补充),一种是通过图形界面(待补充)。
通过以下命令获取:
$ cd android-sdk/platform-tools/systrace
$ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
在低于android4.2的设备上,需要事先做一些配置,当你需要收集如下信息是:
- 收集graphics,aduio以及输入进程信息(通过配置–set-tags= 获取)
- 收集CPU,disk,kernel以及dish activity信息(通过配置option来获取)
$ cd android-sdk/platform-tools/systrace
$ python systrace.py --set-tags=gfx,view,wm
$ adb shell stop
$ adb shell start
注意:无需重启adb服务
完成以上配置后,开始抓trace文件
$ python systrace.py --cpu-freq --cpu-load --time=10 -o mytracefile.html
抓到trace.html文件后,通过web浏览器打开
每个应用程序都有一排代表渲染帧的圆圈,通常为绿色,如果绘制的时间超过16.6毫秒则显示黄色或红色。通过“W”键查看帧。
注意:输入“?”可以查看帮助
点击帧,则下方将显示系统为该帧所做的工作。在运行Android 5的设备(API Level 21)或更高,这项工作分为UI线程和render线程。而在以前的版本中,创建帧的所有工作都是在UI线程上完成的。
点击帧的各个组件,可以查看它们的运行时间,事件(如performtraversals),当你选择某个方法时,也会显示该方法的执行过程。点击最下方的alert,将显示alert的具体信息。
Systrace会自动分析trace event,在alerts中指出性能问题,并且给出相应的建议。
选择慢帧(如图3的黄色圆圈所示)之后,将在底部显示一个警报。在Description一栏中,将看到变慢的原因(ListView在回收和重绘的时候,由于超负荷的工作导致慢帧),trace中有相关事件的链接,可以进一步解释系统在这段时间内正在做什么。
如果许多ListView工作都在UI线程中进行的,那么你可以使用Traceview(https://developer.android.com/studio/profile/traceview.html)代码性能能分析工具,分析具体是在哪一些方法耗时过多。然后,在这些方法上添加trace marker(可参见下一节的见trace应用程序代码)的功能获得更具体的定位。
注意,您还可以通过单击窗口右侧边的Alert选项卡来查找trace中的每个警报,在弹出的侧边框中那里您可以看到trace中警告以及事件计数。
Alert面板会将trace中的问题呈现出来,以及这些问题造成卡顿的频率,
帮助你看到问题发生的痕迹,以及如何他们往往有助于该。Alert面板可以看成一个是待修复的bug列表,通常一个区域的微小变化或改进可以消除应用程序中的所有类警报!
在framework中的trace marker并没有覆盖到你的所有代码,因此有些时候你需要自己去定义trace marker。在Android4.3之后,可以通过Trace类在代码中添加标记,这样你将能够看到在指定时间内应用的线程在做哪些工作,当然,trace 的begin和end操作也会增加一些额外的开销,但都只有几微秒左右。
通过下面的例子来说明Trace类的 用法。
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 {
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);
mDataset.add(rowItem);
} finally {
Trace.endSection();
}
holder.bind(mDataset.get(position));
} finally {
Trace.endSection();
}
}
…
}
注意:endSection和beginSection遵循就近匹配原则,因此注意控制他们的匹配顺序。
注意:begin和end必须在同一个线程中。
注意:如果begin被try catch语句包含了,则endSestion必须放到finally语句块中。
使用应用程序级跟踪Systrace时,您必须指定应用程序包名。
在分析应用程序时,你应该启用应用程序级跟踪,即使你没有在你的应用程序中添加你自己的跟踪标记。只有当你开启了应用级别的trace,许多lib库,如recyclerview,包括trace marker才能提供有用的信息。