安卓应用程序流畅性评测之Dumpsys篇

来源:互联网 发布:量产u盘工具 mac 编辑:程序博客网 时间:2024/05/21 09:03

你的应用运行在一个稳定的60帧每秒(60fps)并且没有丢帧和延迟帧,那么用户就会感觉你的应用是比较平滑流畅的。下面解释了可用于测量UI性能的工具,并提出了将UI性能测量集成到测试实践中的方法。


测量界面性能

为了提高性能,您首先需要测量系统的性能,测试结果来自管道各个部分存在的问题。dumpsys是一个Android自带的工具,将系统服务状态的有趣的信息dump出来。对dumpsys传递gfxinfo参数可以输出当前这个手机的某个应用动画帧的状态。

> adb shell dumpsys gfxinfo "PACKAGE_NAME"


汇总分析帧数据

** Graphics info for pid 10478 [com.dump.package]**
Stats since: 752958278148ns
Total frames rendered: 82189
Janky frames: 35335 (42.99%)
90th percentile: 34ms
95th percentile: 42ms
99th percentile: 69ms
Number Missed Vsync: 4706
Number High input latency: 142
Number Slow UI thread: 17270
Number Slow bitmap uploads: 1542
Number Slow draw: 23342

上面的数据通过收集很多帧反映了你的app的渲染性能和稳定性。


准确分析帧的定时信息

在上一个命令的最后面加上framestats,结果就会包括你执行下面这个命令的前一段时间各个时间点的帧的详情。这对你定位跟中问题很有帮助。


>adb shell dumpsys gfxinfo "PACKAGE_NAME" framestats

这个命令打印出过去的120这个应用产生的每个时间点帧信息,结果为纳秒级别


每一行输出代表这个应用一帧的数据,每一列都描述帧生产管道对应的阶段的时间花费。


Framestats 数据格式

上面的数据格式可以很方便的粘帖在一些脚本和电子表格里面使用,全部时间戳都是纳秒级别。下面分别介绍每一列:

  • Flags 如果这个数值为0那么代表总共帧时间 = FrameCompleted - IntendedVsync。如果不为0那么这一行应该被忽略,因为这个帧产生的这行数据已经被看作正常渲染的异常数据。这意味着layout & draw花费的时间大于16ms,下面说一说这种情况发生的原因:

    1.这个窗口布局改变(比如这个应用的第一帧或者经过了旋转)

        2.当数据有垃圾时间戳可能会跳帧,如果帧率超过60fps或者屏幕任何区域都没有成为一个脏区那么这个帧会被跳过,但是这个并不能判定这个app有问题。

  • IntendedVsync 帧打算开始点,如果这个数值和Vsync不相等则说明UI线程上发生了一些工作,导致其无法及时响应vsync信号。

  • Vsync

    1.这个时间值被用在了这个帧的vsync监听和绘制(比如Choreographer帧回调,动画,View.getDrawingTime()等)

  • OldestInputEvent

    1.这个时间戳代表事件队列的最老的事件,如果这个帧没有对应的事件那么它的数值为Long.MAX_VALUE

    2.这个值主要用于平台工作,对应用开发人员的用处不大。

  • NewestInputEvent

    1.这个时间戳表示事件队列最新的输入事件,如果为零代表这个帧没有事件。

    2.这个值主要用于平台工作,对应用开发人员的用处不大。

    3.通过查看(FrameCompleted - NewestInputEvent),可以大致了解应用有多少延迟。

  • HandleInputStart

    1.将输入事件分派到应用程序的时间戳。

    2.通过查看此时间和AnimationStart相差的时间,可以衡量应用程序花费在处理输入事件上的时间。

    3.如果这个数字高(> 2ms),这表明应用程序花费了异常长的时间处理输入事件,例如View.onTouchEvent(),这可能表明这项工作需要优化,或转移到不同的线程。 请注意,有一些情况,例如启动新Activity或类似Activity的点击事件,那么大于2ms是可以接受的。

  • AnimationStart

    1.这个时间戳表示动画注册在Choreographer

    2.通过查看与PerformTraversalsStart之间的时间差,可以评估所有正在运行的动画(ObjectAnimator,ViewPropertyAnimator和Transitions等常见类)需要多长时间。

    3.如果这个数字高(> 2ms),检查你的应用程序是否已经写了任何自定义动画,或者ObjectAnimators是什么字段动画,并确保它们适合动画。

  • PerformTraversalsStart 如果从此值中减去DrawStart,您可以提取布局和度量阶段完成所需的时间。 (注意,在滚动或动画期间,你希望这应该接近零..)

  • DrawStart 

    1.performTraversals的绘制阶段开始的时间。 这是记录已失效的任何视图的显示列表的起始点。

    2.此和SyncStart的时间差是在视图二叉树中所有无效视图上调用View.draw()所需的时间。

  • SyncQueued

    1.同步请求发送到RenderThread的时间。

    2.这表示同步消息被发送到RenderThread的时间点。 如果这和SyncStart之间的时间相差0.1ms左右,这意味着RenderThread正忙于一个不同的帧。 这用于区分帧做太多的工作和超过16ms预算和帧由于前一帧超过16ms预算而被停止。

  • SyncStart

    1.绘图同步阶段开始的时间。

    2.如果这和IssueDrawCommandsStart之间的时间相差0.4ms左右,它通常表示绘制了很多新的必须上传到GPU的Bitmaps。

  • IssueDrawCommandsStart

    1.硬件渲染器开始向GPU发出绘图命令的时间。

    2.这和FrameCompleted之间的时间差表明了应用程序生成了多少GPU需要做的工作。 这里可以看出过度绘制或低效的渲染等问题。

  • SwapBuffers 调用eglSwapBuffers的时间,相对于平台之外的工作不感兴趣。

  • FrameCompleted 全做完了! 在此帧上工作的总时间可以通过执行FrameCompleted - IntendedVsync来计算。

您可以以不同的方式使用此数据。 一个简单有用可视化的方式是显示不同延迟桶中帧时间(FrameCompleted - IntendedVsync)的柱状图,如下图所示。 这个图表一目了然地显示,大多数帧都非常好 - 远低于16ms的上限时间(以红色描绘),但是几个帧超出了上限时间。 我们可以看到随时间的增长有符合指标的帧还有超出指标的帧。 您还可以根据数据中的许多时间戳,绘制输入延迟,布局花费的时间或其他有趣的指标。


更简单的帧的时间分析

在开发者选项里面如果你设置GPU呈现模式分析为“adb shell dumpsys gfxinfo”,那么这个adb shell dumpsys gfxinfo "package" framestats命令会打印出最近120帧,该数据可用于指示绘图管道的哪些部分可能很慢。

和上面的framestats一样。下图显示了应用程序生成的许多帧花费时间的细目。


每个垂直条表示一帧动画; 它的高度表示计算该帧动画花费的毫秒数。 条形的每个彩色段代表渲染管道的不同阶段,以便您可以看到应用程序的哪些部分可能会是瓶颈。


控制stat收集窗口

framestats和开发者选项设置这两种方式都大约收集最近两秒的数据。 为了精确地控制此时间窗口 - 例如,将数据约束到特定动画 - 您可以重置所有计数器,并聚合收集的统计信息。

>adb shell dumpsys gfxinfo <PACKAGE_NAME> reset

这也可以与dumping命令本身结合使用,连续捕获两秒内的帧。


定位问题

你可以通过dumpsys分析存在的问题,现在你还需要通过systrace来定位问题


自动化UI性能测试

UI性能测试的一种方法是简单地让一个测试者在目标应用程序上执行一组用户操作,或者在视觉上查找问题(jank),或者使用工具驱动的方法花费大量时间来查找它。 但是这种手动方法充满了危险 - 人类感知帧速率变化的能力差异巨大,这也是耗时,乏味和容易出错的。

一种更有效的方法是记录和分析来自自动化UI性能测试的关键性能指标。 Android 6.0包含新的日志记录功能,可以轻松确定应用程序动画中问题(jank)的数量和严重程度,并可用于构建严格的流程以确定当前性能并跟踪未来的性能。

要了解有关Android性能测试的更多信息,请参阅自动性能测试Codelab。 在Codelab中,您将学习如何编写和执行自动化性能测试,并查看结果以了解如何提高应用的性能。

1 0
原创粉丝点击