Open a284628487 opened 6 years ago
Systrace工具可以用来收集和检查系统级上运行在设备上的所有进程的时序信息。它结合了Android内核的数据,如CPU调度器、磁盘活动和应用程序线程,生成HTML报告。
html报告中高亮的帧就有可能是有渲染总是的帧。
该报告提供了Android设备在给定时间内的系统进程的总体图。它还检查捕获的跟踪信息以突出显示它所观察到的问题,例如UI JANK,同时显示运动或动画,并提供关于如何修复它们的建议。但是,SySTACE没有收集应用程序过程中有关代码执行的信息。有关应用程序执行的方法和使用的CPU资源的详细信息,可以使用Android Studio的内置CPU Profiler,或生成跟踪日志并使用TraceView查看它们。
systrace
工具在android-sdk/platform-tools/systrace/
目录下。
python systrace.py [options] [categories]
例如,下面的命令调用SySTACE在10秒的时间内记录设备进程,包括图形处理,并生成名为mynewtrace的HTML报表:
python systrace.py --time=10 -o mynewtrace.html gfx
如果没有指定任何选项或选项,SySTACE生成包含所有可用类别的报表,并使用默认设置。可用的类别取决于所使用的连接设备。
-h | --help
: 显示帮助信息
-l | --list-categories
: 显示tracing categories
-0 file
: 指定输出文件
-t N | --time=N
: 指定捕获时间,如果不指定,则通过enter键结束
-b N | --buf-size=N
: 用于限制获取的数据总大小
-a app-name | --app=app-name
: 指定要进行捕获的app名称。应用程序必须包含跟踪类的跟踪工具调用。在配置应用程序时,应指定此选项。许多库比如RecyclerView,包括在启用应用程序级跟踪时提供有用信息的跟踪工具调用。
categories
: 包括您指定的系统进程的跟踪信息,例如用于渲染图形的系统进程的gfx。您可以使用-L命令运行SySTACE,以查看连接到的设备可用的服务列表。
Systrace对于检查应用程序的UI性能特别有用,因为它可以分析代码和帧速率,以确定问题区域并提出可能的解决方案。
报告列出呈现UI帧的每个进程,并指示沿着时间线呈现的每个帧。在16.6 毫秒内渲染的帧需要每秒保持稳定的60帧,用绿色帧圆表示。渲染时间大于16.6毫秒的帧用黄色或红色帧圆表示。
点击一个框架圆形突出显示它,并提供有关系统完成该框架的工作的附加信息,包括警报。它还展示了系统在渲染该框架时执行的方法,因此您可以研究UI jank的原因。
选择慢速帧后,可能会在报表的底部窗格中看到警报。图3所示的警告指出,框架的主要问题是在ListVIEW循环和重新绑定中花费了太多的时间。在跟踪中有相关事件的链接,这更多地解释了系统在这段时间内所做的事情。
若要查看工具在跟踪中发现的每个警报,以及设备触发每个警报的次数,请单击窗口右侧的“警报”选项卡,如图4所示。警报面板帮助您了解跟踪中出现哪些问题,以及它们对JANK有多频繁。把面板想象成需要修复的bug列表。通常,一个区域中的微小变化或改进可以从应用程序中消除整个类别的警报。
如果在UI线程上看到了太多的工作,你需要找出哪些方法消耗了太多的CPU时间。一种方法是添加跟踪标记(请参阅仪器应用程序代码)到您认为这些瓶颈导致这些函数调用出现在SySTACE中的方法。如果您不确定哪些方法可能会导致UI线程上的瓶颈,可以使用Android Studio的内置CPU Profiler,或生成跟踪日志并使用TraceView查看它们。
因为Systrace只在系统级别显示有关进程的信息,所以很难知道在HTML报告中给定的时间内应用程序执行的方法。在Android 4.3(API级别18)和更高级别中,可以使用代码中的跟踪类来标记HTML报表中的执行事件,通常不需要用代码来记录SySraces的记录,但是这样做可以帮助您了解应用程序的代码的哪些部分可能对挂起线程或UI JANK 有所贡献。这种方法不同于使用Debug类,跟踪类简单地将标志添加到SyrExcel报表,而调试类帮助您通过生成.
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()
// 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);
mDataset.add(rowItem);
} finally {
Trace.endSection();
}
holder.bind(mDataset.get(position));
} finally {
Trace.endSection();
}
}
}
https://developer.android.com/studio/command-line/systrace