Systrace是基于Linux Ftrace功能实现的一套Function Trace工具。通过它可以了解到一段时间内系统任务运行状态,方便分析问题。
Systrace抓取
Systrace可以通过Android monitor和脚本工具两种方法抓取。 1. 脚本:
其中-t表示抓取的时间,-o表示输出的文件名字,后面一串是要抓取的trace的TAG。 2. monitor工具:
点击上图的按钮就会弹出trace选择框,可以设置时间/文件大小/trace TAG等。
添加trace点
1. Java层:
a) import Trace类:import android.os.Trace;
b) 在需要Trace的地方调用trace函数:第一个参数是这个Trace所属的TAG,第
二个是需要在Trace文件中显示的内容。 c) Java层的trace可以是具体的代码块。
Trace.traceBegin(Trace.TRACE_TAG_VIEW,\"relayout Window\"); …… …… Trace.traceEnd(Trace.TRACE_TAG_VIEW); 2. Native层:
a) inclue trace头文件:#include b) 在需要Trace的函数前调用trace:Native层的trace只能以function为单位 void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) { ATRACE_CALL(); Systrace分析 从Systrace可以看出很多信息,下面介绍一些常用的: 1. 从下图可以看出每个CPU的运行状态。 a) C-State表示CPU处于idle状态,可以看到idle状态没有进程运行。 b) 点击CPU上运行的一个进程,可以看到这个进程的一些信息,如下图黑框中 的信息,stateWhenDescheduled表示了这个进程被调度运行时的状态。 c) 点击Clock Frequency,可以看到CPU的频率值。 2. 查看屏幕刷新状态。每帧的间隔和刷新率有关,如果一帧的执行时间超过了刷新率 规定的间隔就会导致卡顿。例如下图trace是从一个帧率为57的机器上抓取的,因此它的间隔基本上是17ms左右。 上图放大后可以看到SurfaceFlinger刷新屏幕数据时的调用关系。调用顺序是从上到下。同时最上面一条表示了这个调用过程中进程的状态:蓝色表示Runnable,绿色表示Running,白色表示Sleep。可以通过这些状态判断进程的状态是否正确,哪里需要优化。 与Surfa 3. 查看锁的状态 通过Trace文件可以看到系统某个进程占有锁的情况。如下图所示,“monitor contention ….”之类的描述就表示了进程锁的状态。 上图中的意思是ActivityManager线程被线程号为1995,名字是Binder809_16的线程block,同时被block的还有两个线程(waiters=2)。ActivityManager线程block的点在TaskChangeNoticationController.java的151行,1995线程获取锁的地方是ActivityManagerService.java的7677行。同时还打印了获取锁的函数。 4. 可以分析应用的启动时间。 Android默认在应用启动的各个关键点都打了Trace,因此可以比较容易的去做一些分析。例如可以看到ActivityThreadMain,bindApplication,activityStart等阶段分别用到底 时间等。 还可以看到SystemServer中启动应用流程的过程,如下图: 5. 可以分析亮屏流程。 可以通过SurfaceFlinger的setPowerModeInternal调用知道LCD初始化花费了多少时间。 通过上面的trace查看亮屏时各个阶段的状态等。 总之Systrace的功能很强大,随着你对Android Framework的了解,可以在自己想要的地方加trace,查看运行状态。 示例 我们尝试用Systrace去分析X6501项目Vulcan导致的应用启动速度变慢的问题。 首先分别抓取底版本和OS版本应用启动时的Systrace 底版本: OS版本: 对比可以看出activityStart阶段,OS版本有很长时间的Sleep。选中这段时间,查看下system server中线程的状态。 可以看到在activityStart的过程有一个Lock等待的操作。选择这个trace点: 可以看到是在调用getInstalledApplications函数时block了,多抓几次trace,可以确定基本上每次都会在这里block。 在该函数中加log,打印堆栈和call uid。 可以看到我们的一个SystemButlerManager会在getContentProvider的时候调用这个函数,通过查询代码可以确定这是VULCAN的Feature。 最终可以确定是由于VULCAN在AMS的startService/getContentProvider等函数中注入代码导致的问题。
因篇幅问题不能全部显示,请点此查看更多更全内容