1. 掉帧基础概念与排查体系总览

1.1 现象识别:什么是掉帧

用户感知到的“卡顿”、“画面撕裂”或“动画不连贯”,在系统层面通常对应三种异常现象:掉帧(Frame Drop)、帧率抖动(Jank)、渲染超时(Missed Frame)。掉帧是其中最常见且影响最直接的性能问题。

现象用户感知系统定义
掉帧画面突然卡住、跳跃、缺失SurfaceFlinger 在某个 vsync 周期内未能合成新帧,重复显示旧帧
帧率抖动视觉上的不平滑、忽快忽慢帧间隔时间(Frame Interval)方差过大,超出人眼舒适区
渲染超时触控反馈延迟、窗口动画拖尾Application 或 SurfaceFlinger 超过 16.6ms 窗口未提交帧
排查第 1 步:收到用户反馈“卡顿”时,不要直接推测是掉帧。先通过
dumpsys SurfaceFlinger --latency
确认是否存在连续的重复显示帧(即 dropped frames),再区分是 App 侧渲染超时还是 SF 侧合成瓶颈。

1.2 数据采集:帧率与刷新率的关系

人眼感知的流畅度由帧率(FPS)和显示刷新率(Refresh Rate)共同决定。刷新率是硬件能力,帧率是软件交付节奏。只有当帧率匹配刷新率的整数倍时,才能获得无撕裂体验。

概念典型值测量工具/命令
屏幕刷新率 (Hz)60 / 90 / 120 / 144
dumpsys display | grep mBaseDisplayInfo
帧率 (FPS)30 / 60 / 90 / 120
dumpsys gfxinfo [包名] framestats
帧间隔 (ms)16.6 / 11.1 / 8.3sysui 打点 | perfetto trace | SurfaceFlinger dump
判断规则(必记):
  • 当 FPS ≤ RefreshRate 且帧间隔稳定 → 流畅(除非 FPS 低于 30)。
  • 当 FPS 偶尔 < RefreshRate,且存在 ≥2 倍的缺失 vsync 周期数 → 掉帧。
  • 当 FPS 接近但不等于 RefreshRate 的整数因子,且帧间隔呈尖刺状抖动 → 帧率抖动,需细查 GPU 或 Buffer 队列。

1.3 原因定位:SurfaceFlinger 合成管线全览

SurfaceFlinger 是 Android 图形系统的中央合成器。每帧的合成经历三个阶段:

  1. 收集(Collect):接收来自多个 App 层(Layer)的 Buffer 提交。
  2. 合成(Compose):将各层按 Z-order 叠加,通过 GPU 或 HWC(Hardware Composer)混合输出。
  3. 送显(Post):将最终帧送入屏幕 BufferQueue,等待 vsync 刷新。

整个管线的瓶颈可能出现在任意一个环节。以下是排查阶段的故障树决策入口:

故障节点典型现象数据采集手段根因方向
App 提交帧超时GPU 栅栏未信号、Buffer 被 stallperfetto slice “Choreographer#doFrame”主线程耗时、过度绘制
SF 合成耗时溢出SF 主线程卡在 “onFrameAvailable”
dumpsys SurfaceFlinger --timing
Layer 过多、Region 复杂、GPU 负载
HWC 回退到 GPU大量 “GLES composition” 日志
dumpsys SurfaceFlinger --list
Overlay 不足、碎片化
vsync 信号漂移vsync 周期不恒定
dumpsys SurfaceFlinger --vsync
调度器干预、GPU fence 延迟

1.4 修复动作与复测

根据上述故障树的指向,修复动作通常分为三类:

  • App 侧:减少过度绘制(Overdraw)、异步渲染(Async)、控制 GPU 纹理大小。
  • SF 侧:减少不必要的 layer、合并冗余层、开启 Hardware Composer 混合优先级。
  • 驱动/系统侧:调整帧调度策略、锁定 GPU 频率、关闭动态刷新率。

复测标准:使用 dumpsys SurfaceFlinger --latency 对比修复前后的 dropped frames 数量 < 5% 总帧数,且帧间隔标准差 < 2ms。

1.5 预防:常态监控与基线

建立帧交付基线:

# 抓取 5 分钟连续掉帧数据,生成基线报告
adb shell dumpsys SurfaceFlinger --latency clear
sleep 300
adb shell dumpsys SurfaceFlinger --latency > baseline_drop.csv

每次版本发布前,用同一场景复验,观测掉帧率是否超过基线 10%。超过即触发告警,进入排查流程。

1.6 掉帧排查流程与合成管线总览

下图将本章知识点串联为一个可执行的排查决策流程:

掉帧排查流程与 SurfaceFlinger 合成管线 ① 现象识别 卡顿 / 撕裂 / 跳帧 ② 数据采集 FPS / 帧间隔 / vsync ③ 原因定位:SurfaceFlinger 合成管线 App 提交 Buffer 队列 SF 收集 Layer 排序 合成引擎 GPU / HWC 送显输出 vsync 刷新 ④ 修复动作 App / SF / 驱动 ⑤ 复测 掉帧率 < 5% ⑥ 预防 / 基线 常态监控 复测未通过 → 回退到原因定位 排查关键入口 dumpsys SurfaceFlinger --latency
本章排查流程小结:
  1. 从 dumpsys 输出 识别掉帧现象(重复帧计数)。
  2. 采集 FPS / 帧间隔 / vsync 稳定性 作为量化指标。
  3. 定位 App → SF → HWC → 送显 管线中的瓶颈环节。
  4. 执行针对性修复,并用复测验证掉帧率是否收敛。
  5. 将修复前后的数据纳入监控基线,防止回归。