第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 排查地图:问题类型分类

基于量化标准,卡顿问题可分为三类。本章给出 故障树,作为后续章节的排查导航图。

卡顿问题类型故障树 — 排查入口导航 应用卡顿 帧率异常 调度延迟 其他类型 渲染超时 GPU 负载高 UI 线程阻塞 CPU 竞争 线程优先级低 中断频繁 内存不足 IO 阻塞 锁竞争 ↓ 排查时从叶子节点反推 → 命中分支 → 进入对应章节

故障树使用说明:遇到卡顿 Trace 时,先根据 帧间隔 和 调度延迟 两个指标判断隶属分支,再匹配叶子节点类型,直接跳转到对应章节的排查流程。

1.5 排查路径总览:从现象到根因的六步闭环

本课程所有章节遵循统一的六步排查闭环。本章作为第 1 步的“坐标系”,其输出直接驱动后续步骤:

步骤 动作 本章产出
① 现象识别 确认卡顿类型与严重等级 量化标准 + 分类框架
② 数据采集 抓取目标 Trace Perfetto 采集命令与配置
③ 原因定位 基于指标下钻到叶子节点 故障树导航 + 排查表
④ 修复动作 针对根因实施优化 (后续章节展开)
⑤ 复测 相同场景验证效果 (后续章节展开)
⑥ 预防 建立监控与回归机制 (后续章节展开)
本章定位总结:完成了“卡顿是什么 → 怎么采 → 怎么量 → 怎么分”的排查前置知识装配。从下一章开始,我们将进入每个叶子节点的实战排查流程。
动手练习:用 Perfetto 采集一次自己应用的日常滑动 Trace,打开 ui.perfetto.dev 加载,找到帧间隔 >16.6ms 的窗口,对照本章故障树判断属于哪一类。这是排查实战的第一步。