第1章 Trace基础与卡顿现象定义
排查逻辑起点 —— 卡顿是用户体验最直接的负反馈。定位卡顿的第一步,不是看代码,而是建立统一的“卡顿语言”:什么是卡顿?用什么量化?有哪些类型?本章为全线排查建立坐标系。
1.1 现象识别:卡顿的用户侧与系统侧表现
卡顿在用户侧表现为界面响应迟缓、动画掉帧、滑动不跟手、点击无反馈。在系统侧则对应为 帧率下降、调度延迟升高、关键线程阻塞 等可测量事件。
| 体验现象 | 系统可观测信号 | 初步判断方向 |
|---|---|---|
| 滑动列表掉帧、动画卡顿 | Choreographer 帧间隔 >16.6ms | 帧率异常 → UI 线程 / GPU |
| 点击按钮后响应延迟 | Input 事件到 Handler 的调度等待 >5ms | 调度延迟 → CPU 竞争 / 优先级 |
| 应用突然冻住几秒 | Binder 事务超时 / 长锁等待 | 阻塞型卡顿 → IO / 锁 / 内存 |
排查口诀:“掉帧先看 UI 与 GPU,延迟先看调度与锁,冻住先看 IO 与内存。” 这是 Trace 分析的三大入口。
1.2 数据采集:Trace 概念与 Perfetto 入门
Trace 是系统行为的全量时序记录,本质是一个带时间戳的事件流。Perfetto 是 Android / Linux 生态的下一代 tracing 平台,统一了 kernel ftrace、atrace、userspace instrumentation 等数据源。
一次标准的卡顿 Trace 采集命令:
# 采集 10 秒,包含调度、CPU、GPU、内存、帧率事件
adb shell perfetto \
-o /data/misc/perfetto-traces/trace.perfetto-trace \
-t 10s \
sched/sched_switch \
gpu/* \
ftrace/print \
android/surfaceflinger \
android/choreographer \
android/input \
memory/*
| 数据源 | 说明 | 排查价值 |
|---|---|---|
| sched/sched_switch | 线程调度切换事件 | 定位线程饥饿、调度延迟、优先级反转 |
| gpu/* | GPU 渲染阶段与频率 | 判断是否 GPU 瓶颈导致掉帧 |
| android/surfaceflinger | SurfaceFlinger 合成与 vsync | 帧率测量、合成延迟 |
| android/choreographer | UI 帧绘制回调 | UI 线程帧间隔与 doFrame 耗时 |
| memory/* | 内存分配与压力事件 | 排查内存不足触发的 kswapd / LMK |
采集注意事项:Trace 本身有 5%~15% 的 CPU 开销,生产环境采集时长不宜超过 30 秒;优先使用
--buffer-size 控制内存占用,避免 OOM 导致 trace 截断。
1.3 原因定位:卡顿的量化标准
卡顿必须被量化才能被系统化排查。本章定义两个核心量化维度:帧率 (Frame Rate) 和 调度延迟 (Scheduling Latency)。
- 帧率标准:Android 系统以 16.6ms (60fps) 或 8.3ms (120fps) 为 vsync 周期。单帧超过周期即产生一次掉帧 (jank)。连续掉帧 = 用户可感知卡顿。
- 调度延迟标准:从“线程就绪”到“实际执行”的时间差。健康值 <2ms,可接受 2~5ms,超过 5ms 即为调度异常,需要排查 CPU 竞争或优先级问题。
以下为卡顿严重等级划分表:
| 等级 | 帧间隔 (60fps) | 调度延迟 | 用户感知 | 排查优先级 |
|---|---|---|---|---|
| 健康 | <16ms | <2ms | 流畅 | — |
| 轻微 | 16~33ms | 2~5ms | 偶尔微卡 | 低 |
| 中等 | 33~50ms | 5~15ms | 明显卡顿 | 中 |
| 严重 | >50ms | >15ms | 冻结感 | 高 |
排查标尺:在 Trace 中,优先搜索帧间隔 >16.6ms 的窗口,再检查对应时间段的调度延迟。两个指标同时恶化,大概率是 CPU 资源竞争;仅帧率恶化而调度正常,则重点排查 GPU 或 UI 线程内部逻辑。
1.4 排查地图:问题类型分类
基于量化标准,卡顿问题可分为三类。本章给出 故障树,作为后续章节的排查导航图。
故障树使用说明:遇到卡顿 Trace 时,先根据 帧间隔 和 调度延迟 两个指标判断隶属分支,再匹配叶子节点类型,直接跳转到对应章节的排查流程。
1.5 排查路径总览:从现象到根因的六步闭环
本课程所有章节遵循统一的六步排查闭环。本章作为第 1 步的“坐标系”,其输出直接驱动后续步骤:
| 步骤 | 动作 | 本章产出 |
|---|---|---|
| ① 现象识别 | 确认卡顿类型与严重等级 | 量化标准 + 分类框架 |
| ② 数据采集 | 抓取目标 Trace | Perfetto 采集命令与配置 |
| ③ 原因定位 | 基于指标下钻到叶子节点 | 故障树导航 + 排查表 |
| ④ 修复动作 | 针对根因实施优化 | (后续章节展开) |
| ⑤ 复测 | 相同场景验证效果 | (后续章节展开) |
| ⑥ 预防 | 建立监控与回归机制 | (后续章节展开) |
本章定位总结:完成了“卡顿是什么 → 怎么采 → 怎么量 → 怎么分”的排查前置知识装配。从下一章开始,我们将进入每个叶子节点的实战排查流程。
动手练习:用 Perfetto 采集一次自己应用的日常滑动 Trace,打开
ui.perfetto.dev 加载,找到帧间隔 >16.6ms 的窗口,对照本章故障树判断属于哪一类。这是排查实战的第一步。