在 Android Studio 中使用 CPU 性能分析器锁定界面卡顿

2022 年 7 月 20 日 谷歌开发者

Android 的用户界面渲染是从应用中 "生成" 一帧然后显示在屏幕上,为了确保用户能够获得顺畅的交互体验,您的应用需要根据设备的刷新率完成每一帧的 "生成"。例如,Pixel 6 设备支持每秒最多渲染 90 帧,这就意味着应用的每一帧任务都要在 1000/90 = 11ms 内完成,如果没有,Android 框架就会将这一帧的渲染跳过,用户就会从视觉上感受到界面运行缓慢,我们称这种情况为 "卡顿"。


出现卡顿的原因有很多种,例如,由应用导致的卡顿或由 SurfaceFlinger 导致的卡顿。本文重点关注由应用导致的卡顿,以及 Android Studio 提供的用于发现和消除这些卡顿的工具,方法是在应用交互的过程中检查记录的轨迹来解决应用的性能问题。


  • SurfaceFlinger
    https://perfetto.dev/docs/data-sources/frametimeline#janks-explained

注意: 本文所展示的是  Android Studio Chipmunk 更新后的卡顿检测界面,使用 Android 12 (API 级别 31) 或更高版本的真机或模拟器。


从实时交互记录轨迹


以下示例使用 GitHub 性能示例仓库中的 JankStatsSample 应用来展示如何使用 CPU 性能分析器锁定卡顿的原因: 

https://github.com/android/performance-samples/tree/main/JankStatsSample

1. 打开 JankStatsSample 并运行应用。

2. 打开 Android Studio 底部的 Profiler 标签页。

3. 点击 Profiler 左侧窗格中的 + 图标启动新的性能分析会话,然后选择要运行性能分析器的设备名称和应用进程。

注意: 虽然可以分析 "可调试应用" (debuggable app),但推荐做法是分析 "可分析应用" (profileable app),因为分析 "可调试应用" 会导致性能开销显著增加。更多详细信息,请参阅关于可分析应用的文档

https://developer.android.google.cn/studio/profile#profileable-apps


4. 点击 CPU 行。


5. 选择 System Trace Recording,点击 Record

6. 与应用互动以收集数据,然后点击 Stop 按钮。Android Studio 将显示 Display 窗格,其中可见卡顿帧,也可以选中 All Frames 复选框,让轨迹记录也显示非卡顿帧。

将鼠标指针悬停在帧上或点击帧,即可查看详细的帧信息。如果选中 All Frames 复选框,将有三种类型的帧。

  • 绿色帧
    不卡顿的正常帧
  • 红色帧
    由于应用进程运行时间超出预期并且错过了预期帧时长的截止时间,被视为卡顿的帧。从应用开发者的角度来看,可操作帧通常是红色帧
  • 黄色帧
    被视为缓冲区填充的帧,这表示应用会在呈现前一帧之前不断将帧发送到系统。这通常是前一帧卡顿所致,应用开发者面对黄帧无能为力。

选中 Lifecycle 复选框,可以切换显示/隐藏四个附加轨迹。

四个轨迹: 

  • Application
  • Wait for GPU
  • Composition
  • Frames on display


Android Studio Bumblebee (2021.1.1) 稳定版中已经加入了这些轨迹信息的显示。您可以在文档中查看每个轨迹的详细说明: 

https://developer.android.google.cn/studio/profile/jank-detection#jank-detection-android-11



检查卡顿帧


接下来,我们来找出卡顿帧出现的原因。


1. 在 Janky frames 轨迹中选择一个卡顿帧,Display 窗格将突出显示相应的生命周期数据,Threads 窗格将突出显示相应的线程数据。

虚线 Deadline 代表截止时间。当帧的时长超过该截止时间时,该帧即被视为卡顿。


您还可以在 Android Studio 的右侧窗格中查看详细分析。

2. 如果您看一下应用主线程相应的轨迹窗格,可以看到大量的时间花费在 "View#draw" 中。

此外,如详细分析窗格中的主线程状态所示,大量线程所处的状态是正在休眠。

3. 我们看一下调用 View#draw 的代码。View#onDrawJankyView 类中被复写: 

https://github.com/android/performance-samples/blob/main/JankStatsSample/app/src/main/java/com/example/jankstats/JankyView.kt#L36
override fun onDraw(canvas: Canvas) {  simulateJank()  super.onDraw(canvas)}

从 onDraw 调用的 simulateJank 方法 定义如下
https://github.com/android/performance-samples/blob/main/JankStatsSample/app/src/main/java/com/example/jankstats/tools/simulateJank.kt#L29
fun simulateJank(    jankProbability: Double = 0.3,    extremeJankProbability: Double = 0.02) {    val probability = nextFloat()
if (probability > 1 - jankProbability) { val delay = if (probability > 1 - extremeJankProbability) { nextLong(500, 700) } else { nextLong(32, 82) }
try { // 在分析器中通过轨迹使卡顿更易被锁定 trace("Jank Simulation") { Thread.sleep(delay) } } catch (e: Exception) { } }}

然后,您可以发现在 simulateJank 方法中调用了 Thread.sleep 。显然,这是因为 JankStatsSample 应用是为了模拟卡顿而特别创建的。但值得注意的是,从卡顿帧的概览再到更详细的分析,可以找出实际代码。

注意: 虽然在这个示例中调用 Thread.sleep 明显有问题,但实际上,在优化实际应用代码时,您将面临更困难的决定。Microbenchmark 开发库有助于衡量所做的更改能否达成预期效果: 
https://developer.android.google.cn/topic/performance/benchmarking/microbenchmark-overview

注意: 系统轨迹显示的是由平台代码和属于应用的库捕获的多个部分,通常没有足够的信息。添加自定义轨迹能够改善这样的情况,添加的方法之一是使用 AndroidX Tracing 库中的 trace(“MySection”) { /* this will be in the trace */ }

  • AndroidX Tracing
    https://developer.android.google.cn/reference/androidx/tracing/Trace

例如,此示例中的 trace(“Jank Simulation”) { … } 显示在相应线程的轨迹部分中。

如需了解关于读取轨迹和添加自定义轨迹的更多信息,请参阅系统轨迹概述:

https://developer.android.google.cn/topic/performance/tracing 


4. 将代码更改为在 onDraw 中不去调用 simulateJank 方法,然后查看是否仍然存在卡顿帧。

override fun onDraw(canvas: Canvas) {  // simulateJank()   super.onDraw(canvas)}


这一次,重新运行系统轨迹录制时,您会发现与应用的交互不再有卡顿帧啦。



加载保存的轨迹


您也可以遵循以下步骤,保存轨迹并后续再加载。保存并加载轨迹后,您可以比较不同版本的跟踪记录或者与他人共享。

注意: 您还可以使用 Macrobenchmark 库 获取系统轨迹:
https://developer.android.google.cn/topic/performance/benchmarking/macrobenchmark-overview

1. 按照从第 1 步至第 6 步的相同步骤,通过实时交互操作录制轨迹。

2. 点击保存图标导出记录。

3. 然后,导航到 + -> Load from file… 加载已保存的系统轨迹录制,选择上一步中导出的已保存文件。

4. 选择要分析的进程。显示进程列表下拉菜单后,输入进程名称的一部分即可快速查找。

然后,您可以加载保存的轨迹,像从实时互动录制一样查看卡顿帧。



总结


本期内容就到这里了,从 Android Studio Chipmunk 开始,您能够看到更精准的性能分析数据,更快锁定应用卡顿。


请查看文档进一步了解 CPU 性能分析器的用法,也欢迎您前往 Android Studio 中的 "Help -> Submit Feedback" 帮助我们改进工具。


  • 文档
    https://developer.android.google.cn/studio/profile/jank-detection#jank-detection-android-11

您还可以在下方查看 Google I/O 大会 上的视频演讲 —— Android 应用性能近期更新 ,其中涵盖了非常丰富的关于性能方面的主题,包括如何避免卡顿帧。

△ Android 应用性能近期更新

我们新发布了一个库,可用于检测和报告在用户设备上运行的应用卡顿,如果您希望了解更加详细的内容,欢迎查看 JankStats 文档:

https://developer.android.google.cn/studio/profile/jankstats 


您可以通过下方二维码或在文章底部私信,向我们提交反馈,分享您喜欢的内容、发现的问题。您的反馈对我们非常重要,感谢您的支持!





 点击屏末  | 进一步了解 CPU 性能分析器的用法





登录查看更多
0

相关内容

代码注释最详细的Transformer
专知会员服务
110+阅读 · 2022年6月30日
【WWW2020-微软】理解用户行为用于文档推荐
专知会员服务
35+阅读 · 2020年4月5日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
Android Studio Chipmunk 现已发布
谷歌开发者
0+阅读 · 2022年6月28日
现代 Android 开发的三大更新 | 2022 I/O 重点回顾
谷歌开发者
0+阅读 · 2022年6月15日
一起看 I/O | Android 开发工具最新更新
谷歌开发者
0+阅读 · 2022年5月20日
Android 游戏开发工具大升级
谷歌开发者
0+阅读 · 2022年4月21日
JankStats 推出 alpha 版本
谷歌开发者
0+阅读 · 2022年3月9日
通过基准配置文件改善应用性能
谷歌开发者
0+阅读 · 2022年3月9日
Android Studio Bumblebee (2021.1.1) 稳定版正式发布
谷歌开发者
0+阅读 · 2022年3月7日
Android 13 首个开发者预览版到来
谷歌开发者
0+阅读 · 2022年2月12日
Android Studio 新特性详解
谷歌开发者
0+阅读 · 2022年1月19日
使用 CameraX Extensions API 将特效应用到照片上
谷歌开发者
0+阅读 · 2021年10月27日
国家自然科学基金
0+阅读 · 2015年12月31日
国家自然科学基金
0+阅读 · 2015年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2011年12月31日
国家自然科学基金
1+阅读 · 2008年12月31日
Arxiv
0+阅读 · 2022年9月19日
VIP会员
相关资讯
Android Studio Chipmunk 现已发布
谷歌开发者
0+阅读 · 2022年6月28日
现代 Android 开发的三大更新 | 2022 I/O 重点回顾
谷歌开发者
0+阅读 · 2022年6月15日
一起看 I/O | Android 开发工具最新更新
谷歌开发者
0+阅读 · 2022年5月20日
Android 游戏开发工具大升级
谷歌开发者
0+阅读 · 2022年4月21日
JankStats 推出 alpha 版本
谷歌开发者
0+阅读 · 2022年3月9日
通过基准配置文件改善应用性能
谷歌开发者
0+阅读 · 2022年3月9日
Android Studio Bumblebee (2021.1.1) 稳定版正式发布
谷歌开发者
0+阅读 · 2022年3月7日
Android 13 首个开发者预览版到来
谷歌开发者
0+阅读 · 2022年2月12日
Android Studio 新特性详解
谷歌开发者
0+阅读 · 2022年1月19日
使用 CameraX Extensions API 将特效应用到照片上
谷歌开发者
0+阅读 · 2021年10月27日
相关基金
国家自然科学基金
0+阅读 · 2015年12月31日
国家自然科学基金
0+阅读 · 2015年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2011年12月31日
国家自然科学基金
1+阅读 · 2008年12月31日
Top
微信扫码咨询专知VIP会员