原文地址:https://developer.android.com/training/testing/performance.html
dumpsys是一款运行在设备上的Android工具,将 gfxinfo命令传递给dumpsys可在logcat中提供输出,其中包含各阶段发生的动画以及帧相关的性能信息。
> adb shell dumpsys gfxinfo < PACKAGE_NAME >
该命令可用于搜集帧的耗时数据。运行该命令后,可以等到如下的 结果:
Applications Graphics Acceleration Info:
Uptime: 102809662 Realtime: 196891968
** Graphics info for pid 31148 [com.android.settings] **
Stats since: 102794621664587ns
Total frames rendered: 105
Janky frames: 2 (1.90%)
50th percentile: 5ms
90th percentile: 7ms
95th percentile: 9ms
99th percentile: 19ms
Number Missed Vsync: 0
Number High input latency: 0
Number Slow UI thread: 2
Number Slow bitmap uploads: 0
Number Slow issue draw commands: 1
HISTOGRAM: 5ms=78 6ms=16 7ms=4 8ms=1 9ms=2 10ms=0 11ms=0 12ms=0 13ms=2 14ms=0 15ms=0 16ms=0 17ms=0 18ms=0 19ms=1 20ms=0 21ms=0 22ms=0 23ms=0 24ms=0 25ms=0 26ms=0 27ms=0
...
...
这里将逐一解释以上重点信息:
- Graphics info for pid 31148 [com.android.settings]: 表明当前dump的为设置界面的帧信息,pid为31148
- Total frames rendered: 105 本次dump搜集了105帧的信息
- Janky frames: 2 (1.90%) 105帧中有2帧的耗时超过了16ms,卡顿概率为1.9%
- Number Missed Vsync: 0 垂直同步失败的帧
- Number High input latency: 0 处理input时间超时的帧数
- Number Slow UI thread: 2 因UI线程上的工作导致超时的帧数
- Number Slow bitmap uploads: 0 因bitmap的加载耗时的帧数
- Number Slow issue draw commands: 1 因绘制导致耗时的帧数
- HISTOGRAM: 5ms=78 6ms=16 7ms=4 … 直方图数据,表面耗时为0-5ms的帧数为78,耗时为5-6ms的帧数为16,同理类推。
那么以上这些数据是怎么统计得到的呢,这时候就要引入framestat了,framestat其实是每一个frame的相信信息,记录这不同阶段下的时间戳。也就是更精准的帧的时间戳信息。
在Android 6.0以后为gfxinfo 提供了一个新的参数framestats,其作用可以从最近的帧中提供非常详细的帧信息,以便您可以更准确地跟踪和调试问题。
> adb shell dumpsys gfxinfo < PACKAGE_NAME > framestats
此命令将应用程序生成的最后120帧信息打印出,其中包含纳秒时间戳。以下是来自adb dumpsys gfxinfo 的示例原始输出framestats:
0 ,27965466202353 ,27965466202353 ,27965449758000 ,27965461202353 ,27965467153286 ,27965471442505 ,27965471925682 ,27965474025318 ,27965474588547 ,27965474860786 ,27965475078599 ,27965479796151 ,27965480589068 ,0 ,27965482993342 ,27965482993342 ,27965465835000 ,27965477993342 ,27965483807401 ,27965486875630 ,
27965487288443 ,27965489520682 ,27965490184380 ,27965490568703 ,27965491408078 ,27965496119641 ,27965496619641 ,0 ,27965499784331 ,27965499784331 ,27965481404000 ,27965494784331 ,27965500785318 ,27965503736099 ,27965504201151 ,27965506776568 ,27965507298443 ,27965507515005 ,27965508405474 ,27965513495318 ,27965514061984 ,
0,27965516575320,27965516575320,27965497155000,27965511575320,27965517697349,27965521276151,27965521734797,27965524350474,27965524884536,27965525160578,27965526020891,27965531371203,27965532114484,
此输出的每一行代表应用程序生成的一帧。每一行的列数都相同,每列对应描述帧在不同的时间段的耗时情况。下一节将详细介绍这种格式,包括每列代表的内容。
由于数据块以CSV格式输出,因此将其粘贴到您选择的电子表格工具中非常简单,或者通过脚本进行收集和分析。下表说明了输出数据列的格式。所有的时间戳都是纳秒。
HANDLE_INPUT_START
ANIMATION_START
你可以用不同的方式使用这些数据。例如下面的直方图,显示不同帧时间的分布(FRAME_COMPLETED - INTENDED_VSYNC),如下图所示。
这张图一目了然地告诉我们,大多数的帧耗时都远低于16ms(用红色表示),但几帧明显超过了16ms。随着时间的推移,我们可以查看此直方图中的变化,以查看批量变化或新创建的异常值。您还可以根据数据中的许多时间戳来绘制出输入延迟,布局花费的时间或其他类似的感兴趣度量。
如果在开发者选项中的CPU呈现模式分析中选择adb shell dumpsys gfxinfo,则adb shell dumpsys gfxinfo
命令将输出最近120帧的时间信息,并将其分成几个不同的类别,可以直观的显示各部分的快慢。
与上面的framestats类似,将它粘贴到您选择的电子表格工具中非常简单,或者通过脚本进行收集和解析。下图显示了应用程序生成的帧每个阶段的详细耗时。
运行gfxinfo,复制输出,将其粘贴到电子表格应用程序中,并将数据绘制为直方图的结果。
每个垂直条代表一帧动画; 其高度表示计算该动画帧所用的毫秒数。条形图中的每个彩色段表示渲染管道的不同阶段,以便您可以看到应用程序的哪些部分可能会造成瓶颈。有关了解渲染管道的详细信息以及如何优化渲染管道,请参阅 Invalidations Layouts和Performance视频。
framestats信息和frame耗时信息通常为2s收集一次(一次120帧,一帧16ms,耗时约2s)。为了精确控制时间窗口,例如,将数据限制为特定的动画 ,您可以重置所有计数器,并重新收集的数据。
> adb shell dumpsys gfxinfo < PACKAGE_NAME > reset
同样 也适用于需要捕获小于2s的数据。
dumpsys是能发现问题或者判断问题的严重性,但无法定位真正的原因。如果要定位原因,应当配合systrace工具使用,请参照systrace工具。
有关Android渲染管道如何工作的更多信息,您可以在其中找到的常见问题以及如何解决这些问题,以下某些资源可能对您有用:
用户界面性能测试的一种方法是简单地让人工测试人员在目标应用上执行一组用户操作,并且可以直观地查找是否出现问题,或者使用工具驱动方法花费大量时间来查找它。但是这种手动方法充满了危险 - 人类感知帧速率变化的能力差别很大,这也是耗时,乏味和容易出错的。
更有效的方法是从自动UI测试中记录和分析关键性能指标。Android 6.0包含新的日志记录功能,可以轻松确定应用程序动画中jank的数量和严重程度,并可用于构建严格的流程以确定当前的性能并跟踪未来的性能目标。
要了解有关Android性能测试的更多信息,请参阅 自动化性能测试代码实验室。在此代码中,您将学习如何编写和执行自动化测试,并查看结果以了解如何提高应用性能。