Systrace 工具

一、概述

1、Systrace简介
Systrace(System Trace)是 Android 4.1 之后,引入的分析设备性能的主要工具。它实际上是其它工具的封装容器(是atrace的主机端封装容器),是用于控制用户空间跟踪和设置ftrace的设备端的可执行文件,也是Linux内核中的主要跟踪机制。
Systrace 允许你收集和检查设备上运行的所有进程的计时信息。 它包括 Android kernel 的一些数据(例如:CPU调度程序,IO、APP Thread),并且会生成HTML报告,方便用户查看分析 trace 内容。
Systrace 利用 ftrace,在系统关键位置都有埋点,主要用于分析系统调用耗时问题,可以自定义trace标签来细化调用栈。使用atrace来启用跟踪,然后读取ftrace缓冲区,并将其全部封装到一个独立的 HTML查看器中。

2、Systrace原理
在系统的一些关键链路(如:System Service、虚拟机、Binder驱动)中插入一些信息(Label),通过 Label 的开始和结束,来确定某个核心过程的执行时间,然后把这些 Label 信息收集起来得到系统关键路径的运行时间信息,进而得到整个系统的运行性能信息。
Android Framework 里面一些重要的模块都插入了 Label 信息(Java层的通过 android.os.Trace 类完成,native层通过 ATrace 宏完成),用户App中可以添加自定义的Label,这样就组成了一个完成的性能分析系统。

3、Systrace使用 —> 获取 Systrace 文件
连接设备,在 Android/Sdk/platform-tools/systrace 目录下,进入终端,执行:$ python systrace.py [options] [categories],一段时间后会自动生成一个 trace.xml 文件,在chrome浏览器中打开,进行查看。
常用的参数:
<1> -o: 指定文件输出的位置和文件名
<2> -t(或 --time): 抓取systrace的时间长度
<3> -a(或 --app): 指定特殊进程包名(注:自己加Label时必须加上!)
( 例如:调用 Systrace 在10s内,记录设备的进程,并生成一个名为 myStrace 的HTML报告:
$ python systrace.py --time=10 -o myStrace.html gfx )

[Systrace 常用的 Tag]
在这里插入图片描述
在这里插入图片描述

4、软件界面介绍
(1)CPU活动:
该区域表示每个CPU中的线程活动的条形图。这些条形会显示所有应用中的CPU活动。CPU活动部分可以展开,展开后可以查看每个CPU的时钟频率。
(2)系统事件:
该区域中的直方图会显示特定的系统级事件,例如:特定对象的纹理计数和大小。
(注:值得仔细检查的直方图是标记为 SurfaceView 的直方图。计数表示已传递到显示管道并等待显示在设备屏幕上的组合帧缓冲区的数量。由于大多数设备都会进行双重或三重缓冲,因此该计数几乎总为:0、1、2)
(3)显示帧:
该区域通常是报告中最顶部的部分,描绘了一条多色线条,后面是成堆的条形。这些形状表示已创建的特定线程的状态和帧堆栈。堆栈的每个层级代表对 beginSection()的调用,或您为应用或游戏定义的自定义跟踪事件的开头。
每个条形堆上方的多色线条表示特定线程,随时间变化的一组状态。线条各颜色含义如下:
<1> 绿色:正在运行
表示该线程正在完成与某个进程相关的工作或正在响应中断。
<2> 蓝色:可运行
表示该线程可以运行,但目前未进行调度。
<3> 白色:休眠
表示该线程没有可执行的任务,可能是因为线程在遇到斥锁定时,被阻止。
<4> 橙色:不可中断的休眠
表示该线程在遇到 I/O 操作时,被阻止或正在等待磁盘操作完成。
<5> 紫色:可中断的休眠
表示该线程在遇到另一项内核操作(通常是内存管理)时,被阻止。

5、查看 trace.html 文件的快捷键
(1)w:放大跟踪时间轴
(2)s:缩小跟踪时间轴
(3)a:在跟踪时间轴上向左平移
(4)d:在跟踪时间轴上向右平移
(5)e:将跟踪时间轴放在当前鼠标位置的中心
(6)g:在当前选定任务的开始处显示网格
(7)Shift + g:在当前选定任务的末尾显示网格
(8)left:在当前选定的时间轴上选择上一个事件
(9)Right:在当前选定的时间轴上选择下一个事件

6、代码中添加 trace 标记的方法
由于 Systrace 是在系统级显示有关进程的信息,因此很难在 HTML 报告中,查看某个特定时间内,该应用程序正在执行什么方法。
在 Android 4.3(API级别18)及更高版本中,可以使用代码中的 Trace类 在 HTML 报告中标记执行事件。 不需要用代码来记录 systrace 的跟踪记录,这样做可以帮助您查看app代码的哪些部分可能导致线程 hung(挂了)或 UI 丢帧。

这种方法与使用 Debug类 不同,Trace类 是简单地将标志添加到 systrace 报告中,而 Debug类 可帮助您生成 .trace文件,并且检查 app CPU 的使用情况。(注:要生成包含已检测的跟踪事件的 systrace HTML 报告,需要添加 -a 或 --app 参数,运行 systrace,并指定应用程序的包名称。)

通常我们在可能引起 jank 代码的地方,添加:Trace.beginSection("标记某个类中的某个方法");Trace.endSection();
就可以查看指定时间段内的 Systrace 信息,如:
在这里插入图片描述
(注意:开始和结束的两个语句必须成对的添加,并且只能同时添加在同一个线程中!)

7、使用 TraceView 分析 trace Log
Traceview 是提供 Systrace 的图形显示工具。 可以通过使用 Debug类 来设置代码来生成 log。 这种跟踪方法非常精确,可以准确指定要启动的代码中的哪个位置,并停止记录 Systrace 数据。 使用 Traceview 检查这些 log 可帮助调试应用程序并剖析其性能。

另外,可以使用命令行中的 dmtracedump 来生成跟踪日志文件的图形调用堆栈图。
如果不需要查看通过使用 Debug类 检测应用程序来记录的 Systrace 日志,则可以使用 Android Studio 3.0 及更高版本中包含的 CPU Profiler来查看应用程序的线程和记录方法跟踪。

(1)trace Log 的打开方法:
打开 Android Device Monitor,选择 File,然后打开 *.trace 文件,查看 trace Log 的内容,进行分析。
在这里插入图片描述
(2)trace Log 的分析:
打开 trace Log 文件后,Traceview 使用以下两个窗口显示 log 数据:
<1> 时间轴窗口:描述每个线程何时进入和退出方法
每个线程的执行都显示在自己的进程中,并且时间向右增加。 每种方法都以不同的颜色显示。 第一行下方的细线显示所选方法的子项(从入口到出口),如下图所示:
在这里插入图片描述
<2> 配置文件窗口:总结每个线程在跟踪日志的执行期间的配置文件
该窗口提供了系统在 Systrace 期间,每种方法执行的列表以及耗时。对于配置文件窗口中的每个顶级节点,表中的 Calls + Rec,Calls / Total 列,将显示该方法调用次数和递归调用次数。或者,对于父级和子级方法,此列显示方法在顶级节点中是方法的子级或父级的调用次数。
在这里插入图片描述
(注意:Systrace可以通过添加Label,来代替TraceView的作用,用来统计方法耗时详情和应用启动时间。)

二、性能问题分析

一般是用 Systrace 分析应用卡顿、启动时间慢、方法耗时等问题。
屏幕绘制的流程为:CPU计算数据 -> GPU绘制界面 -> 数据放入Buffer -> Display从Buffer中取数据呈现。
其中,Display刷新的时间是固定的(Android中为16.6ms),而CPU/GPU计算数据的时间不固定,因此会有很多显示问题(例如:撕裂、丢帧),Systrace可以查看丢帧现场的具体问题点(即:哪些方法耗时过长导致丢帧)。

1、卡顿问题分析(步骤):
(1)找到卡顿的场景,并抓取卡顿发生时的 systrace文件;
(2)找到发生问题的应用进程的主线程,并通过标红的F图标,找到发生问题的问题帧;
(3)通过放大(w)和高亮(m)去判断具体是哪一个细节点发生了耗时情况。
注:若从 systrace文件中,看不出来具体是哪一个方法耗时,我们可以自己在代码中加入Label,去查看方法具体耗时(替代TraceView)。

2、启动时间分析:
很多时候,我们对App的冷启动时间都有一定的要求,通过 Systrace 可以很方便的统计启动时间,并找出耗时的地方。
(注:通过adb命令去启动我们的 MainActivity,然后查看启动时间,并不是真正意义上应用完全打开的启动时间。)
这里,我们统计耗时是从用户点击 Launcher 上的应用图标,到界面完全显示的时间。

有两个方法可呈现界面完全显示的时间:
(1)在 onWindowFocusChange() 方法中打印 Label。(此方法常用!)
即:在该方法中添加:Trace.beginSection("标记某个类中的某个方法");Trace.endSection(); ,示例:

private boolean flag = true;
private static Handler mHandler = new Handler();
@Override
public void onWindowFocusChanged(boolean hasFocus){
	super.onWindowFocusChanged(hasFocus);
	if(hasFocus && flag){
		flag = false;
		mHandler.post(new Runnable(){
			@Override
			public void run(){
				Trace.beginSection("endTime");     // trace添加Lable的开始时刻
				SystemClock.sleep(500);
				Trace.endSelection;          // trace添加Lable的结束时刻
			}
		});
	}
}

从生成的Systrace文件中,可以计算启动时间:
<1> 找到 Launcher 进程中最后一次手指按下的时间点 deliverInputEvent 的标示,这里是起点:
在这里插入图片描述
<2> 终点就是下图中 endTime() 打印时开始的地方,用图中标示的工具,将两段时间相连,就能得到本次应用的冷启动时间为434ms:
在这里插入图片描述
(2)通过 MessageQueue.IdelHandler 来进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值