Android Perfetto 系列 6:为什么是 120Hz?高刷新率的优势与挑战

120 Hz 把显示刷新间隔从 60 Hz 的约 16.67 ms 缩短到约 8.33 ms,但屏幕刷新率、App 产帧率和用户看到的帧并不是同一个数字。这篇从一份 Perfetto Trace 出发,解释三个数字怎样对应,以及高刷新率给渲染和功耗带来的取舍。

第 5 篇已经介绍 Choreographer 的回调顺序,这里重点看更短的显示周期。文中的设备截图只说明那次采集,不能代表所有 120 Hz 机型的调度配置。

本文目录

系列文章目录

  1. Android Perfetto 系列目录
  2. Android Perfetto 系列 1:Perfetto 工具简介
  3. Android Perfetto 系列 2:Perfetto Trace 抓取
  4. Android Perfetto 系列 3:熟悉 Perfetto View
  5. Android Perfetto 系列 4:使用命令行在本地打开超大 Trace
  6. Android Perfetto 系列 5:Android App 基于 Choreographer 的渲染流程
  7. Android Perfetto 系列 6:为什么是 120Hz?高刷新率的优势与挑战
  8. Android Perfetto 系列 7:MainThread 和 RenderThread 解读
  9. Android Perfetto 系列 8:深入理解 Vsync 机制与性能分析
  10. Android Perfetto 系列 9:CPU 信息解读
  11. Android Perfetto 系列 10:Binder 调度与锁竞争
  12. Android Perfetto 系列 11:PerfettoSQL、Trace Processor 与回归检测
  13. Android Perfetto 系列 12:Trace 数据流与丢失排查
  14. Android Perfetto 系列 13:Perfetto SDK、Track Event 与 App 现场 Trace
  15. Android Perfetto 系列 14:heapprofd 与内存 Profiling
  16. Android Perfetto 系列 15:Boot Trace、长时间现场 Trace 与偶发问题抓取
  17. Android Perfetto 系列 16:GPU、Power Counters 与硬件瓶颈分析
  18. Android Perfetto 系列 17:专项场景自动化、问题清单与平台体系
  19. Android Perfetto 系列 18:响应速度实战,从输入事件到首帧反馈
  20. 视频(B站) - Android Perfetto 基础和案例分享
  21. 视频(B站) - Android Perfetto 分享 - 出图类型分享:AOSP、WebView、Flutter + OEM 系统优化分享

如果大家还没看过 Systrace 系列,下面是传送门:

  1. Systrace 系列目录 : 系统介绍了 Perfetto 的前身 Systrace 的使用,并通过 Systrace 来学习和了解 Android 性能优化和 Android 系统运行的基本规则。
  2. 个人博客 :个人博客,主要是 Android 相关的内容,也放了一些生活和工作相关的内容。

欢迎大家在 关于我 页面加入微信群或者星球,讨论你的问题、你最想看到的关于 Perfetto 的部分,以及跟各位群友讨论所有 Android 开发相关的内容

基本概念

什么是屏幕刷新率?

屏幕刷新率表示显示设备每秒更新的次数,单位是赫兹(Hz)。以下是固定模式下的名义间隔;支持可变刷新率的设备会随时调整:

  • 60Hz 屏幕:每秒刷新 60 次,每次刷新间隔约 16.67ms
  • 90Hz 屏幕:每秒刷新 90 次,每次刷新间隔约 11.11ms
  • 120Hz 屏幕:每秒刷新 120 次,每次刷新间隔约 8.33ms

显示刷新率限定了屏幕每秒可呈现的更新次数。显示器可以重复显示上一帧,因此刷新 120 次不等于 App 产生或用户看到 120 个不同画面。

什么是 FPS?

FPS(Frames Per Second)需要说明测量对象:可以指 App 产出的帧数,也可以指最终呈现的新帧数。分析卡顿时应先确定指标取的是哪一侧。

  • 60 FPS 的相邻帧间隔约 16.67 ms。
  • 90 FPS 的相邻帧间隔约 11.11 ms。
  • 120 FPS 的相邻帧间隔约 8.33 ms。

App 帧率低于显示刷新率时,屏幕可以重复上一帧;这不一定叫「掉帧」,24 FPS 视频在高刷屏上就是正常例子。判断交互卡顿要看期望呈现时间、实际呈现时间和帧间隔是否稳定。

  1. 内容类型差异:
  • 视频内容:24 FPS 或 30 FPS 视频不必为 120 Hz 屏幕额外合成 120 个不同画面;播放是否平顺还取决于帧节奏与显示模式。
  • 交互界面:滑动列表和跟手动画更依赖稳定的响应节奏。平均 FPS 相同,偶发长帧仍可能很明显。
  1. 帧率稳定性:帧间隔波动会影响观感;比较两种模式时,应连同场景和逐帧呈现时间一起看。

  2. 系统行为:

  • App 没有新帧时,显示系统可能继续呈现上一帧。
  • App 产帧快于显示节奏时,部分工作可能不会转化为新的可见画面;具体是否丢帧要看缓冲区与呈现记录。

不同应用场景有不同的流畅度标准,开发者需要根据应用类型选择合适的优化策略。

什么是 Vsync?

VSync 给 App 和 SurfaceFlinger 提供与显示刷新相关的调度时点。App 有待处理帧时,Choreographer 会请求相应回调;并非每一次 VSync 都触发 App 绘制。相关相位和偏移在第 8 篇展开。

为什么 120Hz 成为新标准?

120 Hz 模式的主要变化是可见更新机会更密,但它是否有收益取决于内容和设备:

  1. 更密的更新机会:如果 App 能稳定产帧,120 Hz 的滑动和动画比 60 Hz 可以呈现更多中间状态;静态内容没有同样收益。

  2. 缩短等待下一次刷新的上限:名义刷新间隔从 16.67 ms 变为 8.33 ms;端到端输入延迟还包含事件分发、App、GPU 与合成,不能直接写成 16.67 ms 变 8.33 ms。

  3. 设备能力:芯片、面板与散热决定能否持续运行在目标模式;只看到屏幕支持 120 Hz,不能推断 App 也能稳定输出 120 FPS。

  4. 功耗管理:设备可按内容与交互状态切换刷新率,避免静态画面持续使用高刷新模式。

  5. 可变刷新率:支持相应硬件和系统策略的设备可以调整显示模式;可用档位和切换条件以具体机型为准。

苹果的 ProMotion 也采用按场景选择帧率的思路。后文引用它的动画建议,目的是比较调度原则,不把 iOS 数值直接当成 Android 设备的配置。

系统实现与工作原理

Perfetto 视角下的 120Hz 渲染流程

120 Hz 的名义显示周期是 8.33 ms,并不意味着 App 主线程、RenderThread、GPU 和 SurfaceFlinger 必须串行塞进同一个 8.33 ms 窗口。App 的预期完成时间受设备调度相位和 FrameTimeline 预测影响。下图展示了那次 120 Hz 设备的 Trace:

在 120Hz 设备上,我们会看到:

  1. VSync 间隔:图中相邻 VSync 标记约隔 8.33 ms,对应当时的显示模式。
  2. App 回调:有待处理帧时,Choreographer 的 Input、Animation、Traversal 等回调按顺序执行。
  3. 帧预算:目标是满足该帧的预期完成与呈现时点;用 Expected/Actual Timeline 判断是否晚于预期,再查具体阻塞段。

上图中出现了两个 Buffer 相关的 Trace,这里做一个简单的说明:

  1. QueuedBuffer:(例如:QueuedBuffer - VRI[ImproveSnsTimelineUI]#748BLAST#748)
  • 这个 Trace Tag 是在 App 进程中打印的
  • 表示应用完成一帧渲染后,将渲染好的 Buffer 放入队列准备提交给 SurfaceFlinger
  • 在使用 BLASTBufferQueue 的系统中,轨道上升表示有新 Buffer 进入队列;GPU 是否已写完,还要看 acquire fence
  1. BufferTX:(例如:BufferTX - com.tencent.mm/com.tencent.mm.plugin.sns.ui.improve.ImproveSnsTimelineUI#47974)
  • 这个 Trace Tag 是在 SurfaceFlinger 进程中打印的
  • 表示应用提交的 Buffer 已随事务到达 SurfaceFlinger、还在等待被消费(latch)的数量
  • TX 指 Transaction(BLAST 事务):AOSP 中这个计数对应该 Layer 的 mPendingBuffers(trace 名定义为 "BufferTX - " + mName)

正确的流程应该是:

  1. App 的 RenderThread 调用 queueBuffer,此时 App 认为自己已交出一个 Buffer,于是 QueuedBuffer +1。
  2. 该 Buffer 随 BLAST Transaction 被传输给 SF,事务到达 SF 端后,BufferTX +1。
  3. SF 在未来的某个 Vsync 周期 latch(或 drop)这个 Buffer,此时 BufferTX -1;被 drop 的 Buffer 不会上屏,只有被采用的 Buffer 才可能进入后续合成与呈现。
  4. 当 SF 不再需要这个 Buffer 时(例如,它已经被新的帧替换,或者已稳定显示了足够长的时间),SF 会释放(release)这个 Buffer。
  5. SF 释放 Buffer 后,App 会收到 Buffer 已被释放的回调(releaseBufferCallback),此时 App 端的 QueuedBuffer 才会 -1,表示这个 Buffer 已成功返回缓冲池,可被再次使用。

QueuedBuffer 和 BufferTX 是数量变化,不能单靠它们或一条 Actual Timeline 切片证明某个 Buffer 从生产到显示的全过程。选中 App 帧后,继续核对 FrameTimeline 的 token、layer 与 SurfaceFlinger 帧;相关入口见第 1 篇。

支撑 120Hz 的系统架构优化

设备要持续在高刷新模式下运行,需要同时控制帧耗时与功耗。显示模式选择是其中一环。

自适应刷新率技术

Android 设备可结合显示硬件、系统策略和应用帧率请求选择刷新率:

  • 硬件能力:支持可变刷新率的面板能在设备提供的范围内调整刷新节奏;不能假定所有 LTPO 设备都覆盖 1–120 Hz 或连续调节。

  • 系统策略:静态内容、视频、滚动和游戏可能请求不同的显示模式;实际选择还受设备支持档位、电量、温度与厂商策略影响。

  • 应用提示:Surface.setFrameRate() 告诉系统该 Surface 的预期帧率,并不保证显示器切到指定模式。Android 官方文档列出了不切换的情况。

例如,应用以 60 FPS 输出内容时,可给对应 Surface 一个 60 FPS 提示:

1
surface.setFrameRate(60.0f, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT);

这个调用不会让产帧率自动变成 60 FPS;仍需控制应用自己的渲染节奏。

120Hz 的优势与挑战

120Hz 带来的体验提升

我拿到第一台120Hz手机的时候,最直观的感受就是:

  1. 滑动更连贯:拿到第一台 120 Hz 手机时,我最明显的体感来自桌面和信息流滑动。但要把这种体感归因到刷新率,需要在同设备上控制应用帧率和显示模式再比较。

  2. 游戏有更密的反馈机会:游戏稳定产帧且显示模式允许时,新的画面可以更频繁呈现。「提前 8 ms 看到画面」不是固定收益,输入、渲染和显示延迟都要实测。

  3. 阅读体感因人而异:我长时间滑动内容时觉得高刷新模式更舒服;这里是个人感受,没有做盲测,也不能当成视觉健康结论。

  4. 触控与显示分开看:触控采样率和屏幕刷新率是两项规格。高刷可能缩短等待下一次呈现的时间,但不能据此推断触控采样也提高了。

120Hz 面临的实际问题

当然,高刷屏幕也带来了一系列技术挑战:

  1. 功耗:高刷新模式可能增加显示和渲染功耗。没有固定设备、亮度、应用、时长和测量方法,就不能给出统一的耗电百分比。

  2. 帧节奏更紧:若应用目标是稳定 120 FPS,帧间隔约 8.33 ms。App 的具体截止时点仍由 FrameTimeline 预测决定;不能把全部系统工作都算进一段 8.33 ms 的串行预算。

  3. 温度:游戏持续高帧率可能让 CPU、GPU 和显示模块工作更久,随后触发降频。要区分刷新率与游戏负载的影响,需要同机同场景测试。

  4. 应用目标帧率:120 Hz 屏幕上运行 60 FPS 应用不一定是适配失败;视频、静态内容或省电模式可能有意选择较低帧率。

思考与展望

静态页面和快速滑动对刷新率的需求不同。一直请求 120 Hz 会让省电空间变小,实际调度应随内容变化。

苹果的 ProMotion 开发文档按动画类型给出帧率范围:快速、大范围运动可以请求更高帧率,小幅慢速变化使用较低帧率或系统默认值。这是 iOS 的建议,Android 上仍要按设备能力和系统策略验证。

截图中的范围来自苹果文档:

  1. 高影响力动画(High-impact animations):
  • 适用场景:全屏转场(如照片应用中点击缩略图展开)、第一人称游戏、Sheet弹出展示等
  • 推荐帧率:80-120Hz,首选120Hz(CAFrameRateRange(minimum:80, maximum:120, preferred:120))
  • 使用建议:谨慎使用,仅在关键交互场景应用,以减少电量消耗
  1. 透明度/颜色过渡和微小移动:
  • 适用场景:开关状态变化、进度指示器旋转、背景模糊效果等
  • 推荐帧率:使用系统默认帧率范围(CAFrameRateRange.default)
  • 使用建议:这类动画不需要过高帧率,视觉效果差异不大
  1. 低速小动画:
  • 适用场景:时钟指针移动、缓慢进度条等
  • 推荐帧率:根据动画速度,可选择8-15Hz、15-24Hz或30-48Hz不等
  • 使用建议:低帧率在这些场景下视觉效果已足够好,同时可显著节省电量
  1. 其他所有情况:
  • 推荐使用系统默认帧率

这组建议的重点是按内容请求帧率,再在真实设备上检查动画和功耗。请求较低帧率后是否省电,仍取决于面板和系统是否切换显示模式。

电量与体验的权衡

从 120 Hz 切到 60 Hz 可能省电,幅度取决于设备、亮度、内容和应用实际产帧率。没有同条件测试,不能给出统一的「节省 10–15% 电量」结论。

高刷新率的价值主要出现在滑动、动画和其他需要快速反馈的场景。静态内容可以让系统选择较低模式,前提是切换过程没有引入可见抖动。

开发者的适配策略

应用可以用 Surface.setFrameRate() 提示内容的目标帧率,同时控制自己的产帧节奏。系统最终是否采用请求值,要看支持的显示模式、温度、电量和设备策略;在 Android 17 设备上,还要核对是否支持自适应刷新率(ARR)。

复测时至少记录显示模式、App 实际帧率、逐帧呈现时间和功耗条件。只报「设备是 120 Hz」无法说明交互有没有改善。

结论

120 Hz 提供更密的显示更新机会,也让稳定产帧更难。Perfetto 里先看设备当时的刷新模式,再对照 App 与 SurfaceFlinger 的 Expected/Actual Timeline,区分 App 晚完成、合成晚呈现和正常的低帧率内容。功耗结论则需要同设备、同亮度、同场景的独立测量。

关于我 && 博客

下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!

  1. 博主个人介绍 :里面有个人的微信和微信群链接。
  2. 本博客内容导航 :个人博客内容的一个导航。
  3. 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
  4. Android性能优化知识星球 : 欢迎加入,多谢支持~

一个人可以走的更快 , 一群人可以走的更远