概述
UI渲染是指从App生成帧并显示在屏幕上的行为。为了保证App用户体验的流畅性,App需要在16ms内渲染完一帧以达到60fps的帧率(为什么是60fps?)。如果你的AppUI渲染缓慢,那么系统会强制跳过某些帧,用户就会感知到app的“口吃”,也就是卡顿。
定位卡顿
精准地定位App中引起卡顿问题的代码是非常困难的,本小结介绍一些定位卡顿问题的方法:
- 直观分析
- Systrace
- 定制性能监控工具
直观分析可以让你在短时间内查看整个App的卡顿情况,但是它不像Systrace可以提供更多卡顿的细节。Systrace可以提供足够的信息,但如果对App的所有使用场景运用Systrace分析,你会被大量的数据淹没以至于难以分析问题。直观分析和Systrace都可以在你的本地设备上检测卡顿问题,但如果没办法在本地设备上重现卡顿问题,你可以构建自定义的性能监控工具,以便在线上运行的设备上测量App特定部分的性能。
直观分析可以帮助你定位App使用场景中产生卡顿的地方。你可以简单地打开App然后使用它的各个功能来查看界面是否卡顿。以下是做直观分析时候的一些建议:
-
使用release版本(至少是非debuggable)的App。ART运行时为了支持debug的某些特性在debug情况下去掉了好几个非常重要的性能优化点;因此要确保你分析的App是和用户使用接近的版本。
-
打开Profile GPU Rendering。Profile GPU Rendering在屏幕上显示了各种图表,可以帮助你直观地看到绘制UI窗口的每一帧相对16ms每帧的标准花费了多长时间。每个显示栏有各个不同颜色的组件,每个组件都被映射到渲染pipeline的某个阶段,因此你可以看到哪一部分花费了最长的时间。例如,如果某一帧在处理输入的时候花费了较长时间,那你就应该查看一下你的代码里面处理用户输入的部分。
-
某些特定的组件,比如 RecyclerView,它们是常见的卡顿根源,如果你的App使用了这些组件,最好分析使用了这些组件的部分。
-
尽量使用较慢的设备来恶化卡顿问题以便分析。
一旦发现了产生卡顿的场景,或许你已经知道了造成卡顿的原因,但如果你需要更详细的信息来分析问题,可以借助Systrace。
使用Systrace
虽然Systrace是展示整个设备在干什么的工具,它对定位卡顿问题也非常有帮助。Systrace有着非常小的运行时开销,因此你在分析问题的时候可以体验到真实的卡顿。
使用Systrace来记录App卡顿场景下的trace(可以通过 Systrace WalkThrough 来查看如何做)。systrace的图表被进程和线程分为若干个部分,你的app的trace结果大致长这样:
image.png
上图所示的systrace包含着可以定位卡顿的如下信息:
- Systrace显示了每一帧绘制的时间段,并且给每一帧都有不同颜色,可以突出较慢的渲染帧时间。与直观分析相比,这可以帮
助你更精确地找到单独的卡顿的某一帧。更详细的内容可以参考 Inspecting Frames。 - Systrace会监测你App中的问题并会在单独帧和警告栏里面展示警告提示信息;跟着这些提示的指引来分析问是最好的选择。
- 某些 Android 框架和库,比如 RecyclerView有自定义的trace标记,因此systrace的timeline会展示这些方法在何时执行以及执行了多长时间。
在查看了systrace的输出结果之后,你可能会发现某些可疑的造成卡顿的方法。比如:如果timeline显示某一帧过慢是由RecyclerView引起的,你可以给相关代码 添加Trace标记,然后重新运行systrace来获取更多的信息。新版的systrace的timeline会展示你代码里面这些方法的调用的时机以及耗费的时间。
如果没有从systrace中找到为什么UI线程执行较长时间的细节,那么你可能需要使用 AndroidCPU Profiler来记录采样或者插桩的methodtrace。不过通常情况下,methodtrace不适合用来定位卡顿问题,因为它们运行时的开销太高可能会造成误报,并且它无法看到线程是在运行还是处于阻塞状态。但是,method trace可以帮助你定位代码中耗时长的方法;在定位到耗时方法之后,可以 添加Trace标记 然后重新运行systrace来查看是否是因为这些方法引起的卡顿。
修复卡顿
要修复卡顿问题,首先查看那些没有在16.7ms内完成的帧,然后查看造成这个的原因在哪。是因为View#draw反常地花费了较长时间,又或者是布局过程耗时?详细介绍见下文的常见卡顿原因。
要避免卡顿问题,耗时较长的任务应该在UI线程之外异步完成;因此需要时刻注意你的代码运行在哪个线程,并且在post不重要的任务到主线程的时候保持谨慎。
如果你的App有一个复杂而重要的UI,可以考虑 writing instrumentation tests 来自动监测较慢的渲染时间,然后定期运行测试case来避免问题复发。








网友评论