Android 常用的性能分析工具详解:GPU呈现模式, TraceView, Systrace, HirearchyViewer(转)
此篇将重点介绍几种常用的Android性能分析工具:
一、Logcat 日志
选取Tag=ActivityManager,可以粗略地知道界面Displaying的时间消耗。当我们打开一个Activity的时候,log会打印一串log如下:
I/ActivityManager﹕ Displayed xxx.xxx.xxx/TestActivity: +1s272ms (total +3s843ms)
- 第一个时间表示系统接受到打开的intent到TestActivity界面显示出来的时间1.272秒。
- 第二个时间特殊情况下才会有。例如这种调用流程:A->B(在onCreate立刻finish掉自己,直接跳转到C)->C(TestActivity),它包含了B页面onCreate处理以及finish的时间。这个时间如果过长,会导致用户点击跳转后,页面还停留在原来界面,延迟一段时间再跳转。这种体验很差,用户会觉得卡顿并容易点击多次。很多应用程序的入口页面,都设计成这种情况的跳转。
在此我们只讨论第一个时间,在这个时间内系统做了以下事情: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发出接到命令的回复。其实可以简单理解为:红色线<span style="font-family: Arial, Helvetica, sans-serif;">Process时间+GPU返回时</span><span style="font-family: Arial, Helvetica, sans-serif;">GPU</span><span style="font-family: Arial, Helvetica, sans-serif;">与CPU通信的时间</span>
注意:使顺利在60帧,每帧必须小于16毫秒完成。
关于Execute:如果执行耗费了过长的时间,这意味着你是跑在前面的图形管线。 android在运行时可以有3个缓冲区.如果你需要另一个应用程序将阻塞直到其中的一个缓冲区释放出来。两个原因会发生这种情况。第一,你的应用在Dalvik中快速绘制但在GPU显示列表时候消耗了大量时间。第二,你的应用程序花了很长的时间来执行第几帧;一旦管线满了他将无法赶上。
1. 运行TraceView有两种方式
(a).调用Debug类
//在开始调试的地方,如Activity的onCreate函数,添加 Debug.startMethodTracing("tracefilename"); //结束调试的地方,如Activity的onDestroy函数,添加 Debug.stopMethodTracing();
运行app一段时间后,再点击已变成stop method profiling的该按钮。eclipse会自动弹出debug的标签(可通过菜单File->save as保存数据), 界面同上面。这种方式不需要修改代码,所以对于没有源码的程序同样可以进行排查。同时可以方便的进行全局性能排查。
2. TraceView界面信息介绍。TraceView界面包括时间面板和方法面板
(1) 时间面板(Timeline Panel)
时间面板展示了每个线程的执行情况,其中的[1]main即为ui主线程。
移动到某个位置可以查看该点对应的方法的执行信息,点击方法面板则会选中相应的方法。
可以左键按住不放选中区域放大局部精细查看,不同方法用不同颜色标注
(2) 方法面板(Profile Panel)
方法面板展示了所有方法的执行情况,点击某个方法可以查看在对应线程上的执行时间区域,并会显示其父方法及子方法。
每个方法包括如下信息列,可点击某列进行排序,从而确定产生性能问题的函数:
1 Incl Cpu Time 2 Excl Cpu Time 3 Incl Real Time 4 Excl Real Time 5 Incl Cpu Time% 6 Excl Cpu Time% 7 Incl Real Time% 8 Excl Real Time% 9 Calls+RecurCalls/Total 10 Cpu Time/Call 11 Real Time/Call
- 内核部分:Systrace利用了Linux Kernel中的ftrace功能。所以,如果要使用Systrace的话,必须开启kernel中和ftrace相关的模块。
- 数据采集部分:Android定义了一个Trace类。应用程序可利用该类把统计信息输出给ftrace。同时,Android还有一个atrace程序,它可以从ftrace中读取统计信息然后交给数据分析工具来处理。
- 数据分析工具:Android提供一个systrace.py(python脚本文件,位于Android SDK目录/tools/systrace中,其内部将调用atrace程序)用来配置数据采集的方式(如采集数据的标签、输出文件名等)和收集 ftrace统计数据并生成一个结果网页文件供用户查看。
(1)手机准备好你要进行抓取的界面
(2)点击开始抓取(命令行的话就是开始执行命令)
(3)手机上开始操作
(4)设定好的时间到了之后,会将生成Trace文件,使用Chrome将这个文件打开进行分析
- UsingEclipse
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.
- Using Android Studio
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.
- UsingDevice Monitor
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.
- Command Line Usage
1 Usage: systrace.py [options] [category1 [category2 ...]] 2 Example: systrace.py -b 32768 -t 15 gfx input view sched freq 3 Options: 4 -h, --help show this help message and exit 5 -o FILE write HTML to FILE 6 -t N, --time=N trace for N seconds 7 -b N, --buf-size=N use a trace buffer size of N KB 8 -k KFUNCS, --ktrace=KFUNCS 9 specify a comma-separated list of kernel functions to 10 trace 11 -l, --list-categories 12 list the available categories and exit 13 -a APP_NAME, --app=APP_NAME 14 enable application-level tracing for comma-separated 15 list of app cmdlines 16 --link-assets link to original CSS or JS resources instead of 17 embedding them 18 --from-file=FROM_FILE 19 read the trace from a file (compressed) rather than 20 running a live trace 21 --asset-dir=ASSET_DIR 22 -e DEVICE_SERIAL, --serial=DEVICE_SERIAL 23 adb device serial number
(1). 由于在systrace.py中指定了-f -l和-i参数,Systrace将生成CPU频率、负载和状态相关的信息。它们为图中第一个红框所示。由于笔者所测手机CPU为双核,故图中有CPU0和CPU1之分。为行文方便,用CPU N来指代CPU的某个核。
“CPU N“所示行对应于整个测试时间内,某个核上运行的进程信息。
“CPU N C-State“所示行为整个测试时间内,某个CPU状态的变化。C-State取值见下表。
“CPU N Clock Frequency”所示行展示了某个CPU运行的频率。通过点击这一行的色块可以查看某个时间点上CPU N的运行频率。
“cpufreq”:该行所示内容和CPU交互式频率调节器(Interactive Governor)的工作有关。交互式CPU调节器驱动添加了对CPU频率调节事件的跟踪。感兴趣的读者不妨阅读kernel中的 include/trace/events/cpufreq_interactive.h文件以了解更多的信息。
(2). VSYNC:显示了每次Tick Tack的时间大概都在16ms左右
(3). 图中 com.example.systracedemo/com.example.systracedemo.MainActivity所示为应用程序占用显示Buffer的Tick-Tack情况。如果使用时间超过16ms,将导致界面显示迟滞等现象。
(4). 图中SurfaceFlinger行展示了其函数调用的CPU耗时情况(如箭头1所指,SurfaceFlinger中的onMessageReceived函数的运行信息)。
(5). 图中最下部的方框中,详细显示了当前鼠标在时间线中选择的部分(即SurfaceFlinger中的onMessageReceived)的详细信息。
1 Key Description 2 w Zoom into the trace timeline. 3 s Zoom out of the trace timeline. 4 a Pan left on the trace timeline. 5 d Pan right on the trace timeline. 6 e Center the trace timeline on the current mouse location. 7 g Show grid at the start of the currently selected task. 8 Shift+g Show grid at the end of the currently selected task. 9 Right Arrow Select the next event on the currently selected timeline. 10 Left Arrow Select the previous event on the currently selected timeline. 11 Double Click Zoom into the trace timeline. 12 Shift+Double Click Zoom out of the trace timeline.
Android framework 里面已经有很多trace的代码。你也可以仿照在自己一些方法里加入trace 跟踪调试。你需要保证 traceBegin 与 traceEnd 一定要成对出现,并且一定要在同一个线程里面。
1 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals"); 2 try { 3 //TODO your work 4 } finally { 5 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 6 }
http://developer.android.com/tools/debugging/systrace.html
http://developer.android.com/tools/help/systrace.html
五、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文件即可。连接后如下图:
- Load View Hierarchy: 界面的控件层次,查看界面中各个控件的层次结构关系
- Inspect Screenshot : 精确查看模式,开发者可以随意点界面的任意一部分,进行放大或缩小观察以查看界面中各控件的具体位置和情况
(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检视的利器。