在开发应用时,需要确保UI交互顺滑,有60fps的帧率。如果出现了丢帧现象,解决问题的第一步是弄清楚系统都做了什么。
Systrace工具可以收集和检查所有进程的时序信息,展示什么地方在占用CPU,以及每个进程和线程每个时间段在做什么。它也会检查捕获到的trace信息,高亮显示发现的问题。
概述
Systrace帮助你分析应用如何在Android设备上运行。它将系统线程和应用线程的执行放在同一时间线上。要使用Systrace分析应用,你首先需要收集trace日志。
图1展示了捕获到的5s时长的滑动一个性能不太好的app的trace信息。默认会显示一个缩小的视图。横坐标是时间,纵坐标是分组进程信息,进程内部按照线程分组。
分组的顺序是Kernel,SurfaceFlinger,接下来是各个应用,以包名为标签。每个应用程序进程包含每个线程所包含的所有trace标记,包括基于启用trace类别的高级trace事件的层次结构。
生成trace
生成trace有两个条件:
- Android系统最低为4.1(API 16)
- 有root权限
生成trace可以使用命令行或者从IDE启动。
命令行生成trace
命令行的方式在4.2和4.3系统上是不同的。
在Android 4.3(API 18)及以上系统生成trace
步骤:
- 确保连接了设备并开启了debug模式
- 运行trace,比如:
$ cd android-sdk/platform-tools/systrace $ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
- 在设备上执行你想观察的动作。
详细的参数信息,参照https://developer.android.google.cn/studio/profile/systrace-commandline.html#options-4.3
在Android 4.2(API 17)及以上系统生成trace
见https://developer.android.google.cn/studio/profile/systrace-commandline.html#options-pre-4.3
Android Studio生成trace
- 连接设备
- 在Android Studio中打开应用,并在设备中运行。
- 在Android Studio中打开Android Device Monitor:Tools -> Android -> Android Device Monitor,
-
然后选中DDMS标签。点击左侧你要追踪的应用,然后点击Systrace按钮:
-
在弹出的窗口中,配置你的设置:
- Destination File:trace文件的保存位置
- Trace duaration:默认5s,推荐30s。
- Trace Buffer Size:trace大小
- Enable Application Traces from:选择你的应用
- Select tags to enable:至少选择一个追踪标记。
- 点击OK开启trace
- 操作你的应用
- trace结束后,会自动返回到Android Device Monitor。
trace分析
生成trace后,使用浏览器打开trace文件。
帧检测
以下图为例:
每个渲染帧的应用都会展示一行帧的圆圈(F圆圈),典型的是绿色的。黄色和红色的圆圈表示该帧的渲染时间超过了16.6s。
你可以用鼠标点选每一帧来高亮显示该帧,或者点选帧内的元素,最下面的窗口会显示一些详细信息。
查看警告
Systrace会自动分析trace,并高亮性能问题作为警告,对处理方式提出建议。
如上图所示,在你选择了一个耗时较长的帧后,一个警告会显示出来。查看警告的描述,对查找问题很有帮助。上述表示Adapter的getView方法可能做了太多的工作。
你也可以点击右侧的Alerts标签来查看trace中所有的警告:
快捷键
键 | 描述 |
---|---|
w | 放大 |
s | 缩小 |
a | 左移 |
d | 右移 |
e | 定位到中间位置 |
g | 显示网格线 |
← | 选择上一个 |
→ | 选择下一个 |
trace代码
框架定义的trace标记并不适用所有的情况,所以你可能需要添加你自己的标记。在Android 4.3(API18)以上的系统,你可以使用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();
}
}
…
}
注意:
- begin和end是成对出现的。
- begin和end必须在同一线程内。
- try...catch块中,确保end在finally中。
在测试应用性能时,应该打开应用级trace,即使你没有自己添加标记。很多库,比如RecyclerView,包含了一些trace标记,可以提供很多有用的信息
**注:本文翻译自Google官方文档。