第2章:用户感知与量化指标

帧率抖动的直接受害者是用户。理解用户感知与各量化指标之间的映射关系,是建立高效排查体系的第一步。本章定义五个核心指标及其采集、判读方法,并给出指标异常的通用排查路线。

现象识别:用户眼中的「卡」与「顿」

用户在界面滑动、动画过渡、列表滚动时感受到的异常可归纳为三类:

  • 微卡顿:肉眼可见的非连续跳跃,持续1~3帧,常见于布局重绘或轻量GC。
  • 冻结:界面完全停止响应超过100ms,通常由主线程长时间同步任务或死锁引发。
  • 掉帧跑马灯:短时间内连续丢帧,造成视觉上的“水波纹”感,多在复杂列表或合成阶段出现。
关键映射:用户感知到的每次“卡”都是帧时间 > 16.67ms(60Hz)或 > 8.33ms(120Hz)的累积。但单帧超时≠必然卡顿,需要结合丢帧密度和模式判断。

数据采集:五维指标的定义与获取

指标定义采集手段典型阈值
丢帧率统计周期内帧时间超出目标帧间隔的帧数占总帧数的比例Choreographer.FrameCallback / systrace trace
adb shell dumpsys gfxinfo [package] framestats
< 5% (90Hz以上推荐 < 3%)
平均帧时间统计周期内所有帧时间的算术平均值同上 + SurfaceFlinger dump
adb shell dumpsys SurfaceFlinger --latency [Surface]
< 16ms (60Hz) / < 8ms (120Hz)
90%百分位帧时间排序后第90%位置的帧时间,反映“大部分场景”体验从完整帧时间序列排序截取< 20ms (60Hz) / < 10ms (120Hz)
帧时间标准差帧时间序列的离散程度,放大异常抖动
stddev(frametimes_list)
< 4ms (60Hz) / < 2ms (120Hz)
卡顿指数综合丢帧时空分布的加权值,由框架层计算Android FrameMetrics API / JankTracker
FrameMetricsStore.reportJank
< 2.0 (Google推荐)
采集陷阱:adb dumpsys gfxinfo 获取的是过去120帧数据,但系统已丢弃最古老历史。如需全量逐帧采样,应使用 Choreographer 注册 FrameCallback 或集成 FrameMetricsListener。

原因定位:指标异常→排查方向

以下故障树从指标异常向下逐层分解:

帧率抖动指标排查故障树 用户感知异常(卡顿/冻结/掉帧) 丢帧率 > 5% 平均帧时间偏高 90%位帧超限 帧时间标准差大 GPU 渲染 超时 主线程 阻塞 CPU 频率 不足 虚拟化 开销 合成 洪峰 缓冲区 饥饿 多重短 抖动叠加 Shader编译 /过度绘制 CPU升温 降频 Hardware Composer GPU 频率抖动

排查表:指标异常与初步方向

指标异常模式优先级检查入口常见根因
丢帧率高 + 平均帧正常立即Choreographer 回调耗时 / 单帧渲染时间偶发GC / 字体内存分配 / 动态位图加载
90%位帧异常大且标准差小高SurfaceFlinger 合成耗时HWC 未开启 / 图层数超限 / 合成策略降级
帧时间标准差显著增大中systrace 看 CPU 频率 / 中断 / Binder 调用DVFS 配置不当 / 热管制 / 多核调度失衡
卡顿指数 > 2.0紧急FrameMetricsStore 逐帧密度分析连续多帧超时,需定位到具体帧区间

修复动作:为指标优化而生的通用手段

  • 丢帧率优化:预加载字体/资源、批量GC配置、禁用动画中全局layout。
  • 平均帧时间优化:CPU governor 调为 schedutil、减少 Binder 同步调用、禁用软件 vsync 等待。
  • 90%位帧优化:提高合成优先级、限制最大图层数、启用 GPU 合成加速。
  • 标准差优化:锁定 GPU 最低频率、使用 CPU 亲和性绑定渲染线程、减少 warm-up 时小段压力。
  • 卡顿指数优化:监控连续3帧超时模式,对触发段进行弱化(降低帧复杂度)或延迟。
经验规则:90%位帧时间对“优化后的用户体验”敏感度最高。一次成功的优化应使该指标下降幅度超过丢帧率下降幅度。

复测:确认指标改善的验证清单

  1. 在相同场景下运行30秒以上,采集至少三组数据,取中位数。
  2. 对比优化前后的五维指标,要求每个指标均改善或至少不恶化。
  3. 使用
    adb shell dumpsys gfxinfo [package] profiles
    确认渲染管道各阶段耗时是否均衡。
  4. 若仅单一指标改善而其他恶化,需重新评估改动 trade-off。

预防:构建指标基线联控体系

  • 每日回归:在 CI 中运行
    adb shell am start -n [package] --start-profiling
    并解析丢帧率和90%位帧时间,超出基线 10% 自动标记。
  • 兜底阈值:卡顿指数 > 1.5 即弹出 logcat 警告,> 2.5 触发 bugreport 自动采集。
  • 监控仪表盘:将帧时间标准差与 CPU 频率曲线叠加,识别异常频率拐点。
本章小结:五个指标从不同维度刻画帧率稳定性。丢帧率回答“数量”,90%位帧回答“体验上限”,标准差回答“稳定度”,卡顿指数回答“感知密度”。故障树和排查表可快速定位异常指向,修复动作应优先针对 90%位帧和标准差两个敏感指标。