此篇将重点介绍几种常用的Android性能分析工具:
一、Logcat 日志
选取Tag=ActivityManager,可以粗略地知道界面Displaying的时间消耗。当我们打开一个Activity的时候,log会打印一串log如下:
I/ActivityManager﹕ Displayed xxx.xxx.xxx/TestActivity: +1s272ms (total +3s843ms)
在此我们只讨论第一个时间,在这个时间内系统做了以下事情:ActivityManager做一些task相关的处理 -> 应用内创建Activity实例 -> Activity的onCreate->Activity的onResume->布局的初始化->首次绘制的一些东西,这个流程是指一个Activity在一个task初次创建的情况。如果是clearTop等流程,可能还涉及其他Activity的finish,自己onNewIntent等流程。
二、GPU呈现模式分析(Peofile GPU Rendering tool)
1. 在adnroid手机上开启这个功能:打开“开发者选项”->“GPU呈现模式分析”->“在屏幕上显示为条形图”
GPU呈现模式用来测量app的帧速率,属于GPU Profile工具的一种.目前安卓基础60fps以满帧数计算,60fps在一秒没绘制造成,所以可以计算出1÷60≈1.66(绘制每帧需要的时间约为16ms)
2. 开启GPU呈现模式之后,当你的应用程序在运行时,你会看到一排柱状图在屏幕上,从左到右动态地显示,每一个垂直的柱状图代表一帧的渲染,越长的垂直柱状图表示这一帧需要渲染的时间越长.随着需要渲染的帧数越来越多,他们会堆积在一起,这样你就可以观察到这段时间帧率的变化.
(1). 绿色水平线代表16ms,要确保一秒内打到60fps,你需要确保这些帧的每一条线都在绿色的16ms标记线之下.任何时候你看到一个竖线超过了绿色的标记现,你就会看到你的动画有卡顿现象产生.
(2). 蓝色代表测量绘制的时间,或者说它代表需要多长时间去创建和更新你的DisplayList.在Android中,一个视图在可以实际的进行渲染之前,它必须被转换成GPU所熟悉的格式,简单来说就是几条绘图命令,复杂点的可能是你的自定义的View嵌入了自定义的Path. 一旦完成,结果会作为一个DisplayList对象被系统送入缓存,蓝色就是记录了需要花费多长时间在屏幕上更新视图(说白了就是执行每一个View的onDraw方法,创建或者更新每一个View的Display List对象).当你看到蓝色的线很高的时候,有可能是因为你的一堆视图突然变得无效了(即需要重新绘制),或者你的几个自定义视图的onDraw函数过于复杂.
(3). 红色代表执行的时间,这部分是Android进行2D渲染 Display List的时间,为了绘制到屏幕上,Android需要使用OpenGl ES的API接口来绘制Display List.这些API有效地将数据发送到GPU,最总在屏幕上显示出来.
(4). 橙色部分表示的是处理时间,或者说是CPU告诉GPU渲染一帧的时间,这是一个阻塞调用,因为CPU会一直等待GPU发出接到命令的回复,如果柱状图很高,那就意味着你给GPU太多的工作,太多的负责视图需要OpenGL命令去绘制和处理.
3. 如果需要分析具体详细的数据,需要结合下面的命令来进行:
$ adb shell dumpsys gfxinfo your_package
执行该命令产生的日志中,你会发现一个标题为: Profile data in ms. 这一节包含为每个窗口所属应用产生的3列表格。 为了使用这些数据, 简单的复制表格到你喜欢的电子表格软件中就会生成一个堆叠柱状图表。下面的图是借用网上他人的测量结果:
上图每列给出渲染每帧大概需要多长时间:
(1). Draw 对应于蓝色线:是消耗在构建java显示列表DisplayList的时间。说白了就是执行每一个View的onDraw方法,创建或者更新每一个View的DisplayList对象的时间。
(2). Process 对应于红色线:是消耗在Android的2D渲染器执行显示列表的时间。你的视图层次越多,要执行的绘图命令就越多。
(3). Execute 对应于橙色线:是消耗在排列每个发送过来的帧的顺序的时间.或者说是CPU告诉GPU渲染一帧的时间,这是一个阻塞调用,因为CPU会一直等待GPU发出接到命令的回复。其实可以简单理解为:红色线Process时间+GPU返回时GPU与CPU通信的时间
注意:使顺利在60帧,每帧必须小于16毫秒完成。
关于Execute:如果执行耗费了过长的时间,这意味着你是跑在前面的图形管线。 android在运行时可以有3个缓冲区.如果你需要另一个应用程序将阻塞直到其中的一个缓冲区释放出来。两个原因会发生这种情况。第一,你的应用在Dalvik中快速绘制但在GPU显示列表时候消耗了大量时间。第二,你的应用程序花了很长的时间来执行第几帧;一旦管线满了他将无法赶上。
//在开始调试的地方,如Activity的onCreate函数,添加
Debug.startMethodTracing("tracefilename");
//结束调试的地方,如Activity的onDestroy函数,添加
Debug.stopMethodTracing();
之后运行你的app一段时间并退出会在sd卡根目录生成tracefilename.trace这个log文件,记录这段时间内的运行信息。将日志文件pull到PC端,cd到android sdk tools文件夹内(或绑定sdk tools目录到系统path内),运行traceview tracefilename.trace即可打开TraceView分析界面,如下
运行app一段时间后,再点击已变成stop method profiling的该按钮。eclipse会自动弹出debug的标签(可通过菜单File->save as保存数据), 界面同上面。这种方式不需要修改代码,所以对于没有源码的程序同样可以进行排查。同时可以方便的进行全局性能排查。
2. TraceView界面信息介绍。TraceView界面包括时间面板和方法面板
(1) 时间面板(Timeline Panel)
时间面板展示了每个线程的执行情况,其中的[1]main即为ui主线程。
移动到某个位置可以查看该点对应的方法的执行信息,点击方法面板则会选中相应的方法。
可以左键按住不放选中区域放大局部精细查看,不同方法用不同颜色标注
(2) 方法面板(Profile Panel)
方法面板展示了所有方法的执行情况,点击某个方法可以查看在对应线程上的执行时间区域,并会显示其父方法及子方法。
每个方法包括如下信息列,可点击某列进行排序,从而确定产生性能问题的函数:
Incl Cpu Time
Excl Cpu Time
Incl Real Time
Excl Real Time
Incl Cpu Time%
Excl Cpu Time%
Incl Real Time%
Excl Real Time%
Calls+RecurCalls/Total
Cpu Time/Call
Real Time/Call
所有的Time都是以毫秒计算。每列具体含义及作用如下:
1. In Eclipse, open an Android application project.
2. Switch to the DDMS perspective, by selecting Window > Perspectives > DDMS.
In the Devices tab, select the device on which to run a trace. If no devices are listed, make sure your device is connected via USB cable and that debugging is enabled on the device.
3. Click the Systrace icon at the top of the Devices panel to configure tracing.
4. Set the tracing options and click OK to start the trace.
1. In Android Studio, open an Android application project.
2. Open the Device Monitor by selecting Tools > Android > Monitor.
3. In the Devices tab, select the device on which to run a trace. If no devices are listed, make sure your device is connected via USB cable and that debugging is enabled on the device.
4. Click the Systrace icon at the top of the Devices panel to configure tracing.
5. Set the tracing options and click OK to start the trace.
1. Navigate to your SDK tools/ directory.
2. Run the monitor program.
3. In the Devices tab, select the device on which to run a trace. If no devices are listed, make sure your device is connected via USB cable and that debugging is enabled on the device.
4. Click the Systrace icon at the top of the Devices panel to configure tracing.
5. Set the tracing options and click OK to start the trace.
Usage: systrace.py [options] [category1 [category2 ...]]
Example: systrace.py -b 32768 -t 15 gfx input view sched freq
Options:
-h, --help show this help message and exit
-o FILE write HTML to FILE
-t N, --time=N trace for N seconds
-b N, --buf-size=N use a trace buffer size of N KB
-k KFUNCS, --ktrace=KFUNCS
specify a comma-separated list of kernel functions to
trace
-l, --list-categories
list the available categories and exit
-a APP_NAME, --app=APP_NAME
enable application-level tracing for comma-separated
list of app cmdlines
--link-assets link to original CSS or JS resources instead of
embedding them
--from-file=FROM_FILE
read the trace from a file (compressed) rather than
running a live trace
--asset-dir=ASSET_DIR
-e DEVICE_SERIAL, --serial=DEVICE_SERIAL
adb device serial number
3. 下面,我们通过一个示例来展示Systrace的使用
Key Description
w Zoom into the trace timeline.
s Zoom out of the trace timeline.
a Pan left on the trace timeline.
d Pan right on the trace timeline.
e Center the trace timeline on the current mouse location.
g Show grid at the start of the currently selected task.
Shift+g Show grid at the end of the currently selected task.
Right Arrow Select the next event on the currently selected timeline.
Left Arrow Select the previous event on the currently selected timeline.
Double Click Zoom into the trace timeline.
Shift+Double Click Zoom out of the trace timeline.
找到你要分析的进程ID, 分析每个线程在一段时间类具体做什么工作。如果你发现某个方法耗用了很长时间。 可以去代码里面搜索去具体的实现。
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals");
try {
//TODO your work
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
五、HierarchyViewer
1. 如何使用HierarchyViewer ?
Hierarchy Viewer是随Android SDK发布的工具,位于Android SDK/tools/hierarchyviewer.bat (Windows操作系统,mac上显示的为hierarchyviewer),使用起来也是超级简单,通过此工具可以详细的理解当前界面的控件布局以及某个控件的属性(name、id、height等),调试UI界面分析其性能。
(1)连接设备真机或者模拟器(真机可能无法连接,我用的2.3,连接上了,没读到内容)
(2)启动你要观察的应用
(3)打开Hierarchyviewer,点击hierarchyviewer文件即可。连接后如下图:
(4)点击“Load View Hierarchy”, 然后双击下图最上面的Focused Window,这个是当前窗口,加载完毕后会显示当前界面层次结构。
(5)观察层次结构图,这个图有点大,可以拖动。View Hierarchy窗口显示了Activity的所有View对象,选中某个View还可以查看View的具体信息,最好选择工具中的Show Extras选项。
(6)观察单个view,选择单个view后会出现如下图所示图形:
这里会看到Measure、Layout、Draw的耗时。View节点中带有红色或黄色的点代表速度较慢的View对象。请注意,低性能并不表示一定有问题,特别像是ViewGroup对象,View的子节点越多,结构越复杂,性能越差。只要看每个View节点的颜色就可以找到(布局或绘制)最慢的View对象是哪个,这样你就能快速确定问题。
不合理的布局会使我们的应用程序UI性能变慢,HierarchyViewer能够可视化的角度直观地获得UI布局设计结构和各种属性的信息,帮助 我们优化布局设计。
HierarchyViewer是我们优化程序的工具之一,它是Android自带的非常有用的工具,可以帮助我们更好地检视和设计用 户界面(UI),绝对是UI检视的利器。