Perfetto 时间线:抓取、阅读与定位卡点
2026/8/9大约 4 分钟性能与稳定性Android 14Perfettotrace性能分析
Perfetto 时间线:抓取、阅读与定位卡点
上一章建立了方法论。这一章回答:Perfetto trace 怎么抓、怎么读,如何从线程调度中找到 那个“卡住的关键线程”?
一份有用的 trace 必须覆盖故障前后,并包含回答问题所需的数据源。分析时先按日志或交互 标记缩小时间段,再观察主线程处于 Running、Runnable 还是 Sleeping,随后追查唤醒与依赖方。
先锁定时间段与关键线程
| 常见误解 | 正确理解 |
|---|---|
| trace 越大越全越好 | 要有目标地抓:先知道要看线程调度、帧、还是 Binder |
| 看 trace 就是看 log | trace 是时间线,能回答“某时刻谁在跑、谁在等” |
| 掉帧就一定是应用慢 | 可能是调度延迟、Binder 等待、内存回收或系统负载 |
核心结论
- 抓取要有目标:至少包含 sched(调度)、freq(频率)、atrace 与目标服务轨道。
- 阅读顺序:先找目标进程,再找目标线程,最后看该线程的状态与等待原因。
- 关键状态:R(运行)、R+(可运行未调度)、S/D(阻塞)、Uninterruptible(D)最可疑。
- 常见卡点:主线程 Binder 等待、锁竞争、GC、内存回收、调度抢占。
- 帧轨道(FrameTimeline)直接标注掉帧,可反查对应时间段的线程状态。
抓取与定位主链
逐步解释:
- 确定目标:先想清楚要看帧、ANR 还是启动,选择对应轨道。
- 抓取:用 perfetto 命令按需采集。
- 导入:把 trace 拖入 Perfetto UI 或本地打开。
- 定位:按包名找到进程与线程。
- 分析:看线程状态与等待原因,确认卡点。
常用抓取命令
环境:开发设备或模拟器;开发者选项已开启 USB 调试。
adb shell perfetto -o /data/misc/perfetto-traces/trace.perfetto-trace \
-t 10s sched freq idle atrace am wm view input gfx
adb pull /data/misc/perfetto-traces/trace.perfetto-trace抓取前先复现问题并记录时间点;trace 结束后立即停止复现,避免污染时间线。
源码证据
阅读目标:确认帧时间线的来源。
正文指针:FrameTimeline(frameworks/base/libs/frametimeline/ 或 libs/frametimeline);Choreographer.java 的 VSync 回调。
// Choreographer.java(伪代码,行号以 r75 为准)
void doFrame(long frameTimeNanos, int frame) {
// 每帧回调:测量、布局、绘制在此执行
}这段代码证明: 帧轨道的“doFrame”来自 Choreographer 回调;Perfetto 帧轨道把回调 时长与期望帧时间对比,超出的就是掉帧,可以反向定位阻塞线程。
验证与排障
环境:抓取后在本机或 Perfetto UI 分析。
adb shell dumpsys gfxinfo <包名> framestats
adb shell dumpsys gfxinfo <包名> | grep -E "Janky|Total frames"framestats 给出逐帧数据;结合 Perfetto 帧轨道交叉验证。掉帧先看是哪一段超预算 (输入/动画/测量/绘制/合成),再回到对应时间段查线程状态。
常见误区
- “trace 越全越好”:没有目标的 trace 噪声大、定位慢。
- “看 log 顺序代替时间线”:时间线能回答 log 回答不了的同时性。
- “掉帧一定在 doFrame”:可能是输入延迟、调度或合成侧。
- “D 状态一定有问题”:I/O 会短暂 D,长时间 D 才可疑。
延伸问题
- sched 轨道里 R、R+、S、D 分别表示什么?
- 如何从 trace 里看 Binder 调用耗时?
- 如何对比两次抓取定位“偶发卡顿”?
- ftrace 与 atrace 轨道分别来自哪里?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
Choreographer.java | doFrame() | 帧回调 |
libs/frametimeline/ | 帧时间线 | 掉帧标注 |
| 内核 ftrace | sched 事件 | 线程调度 |
dumpsys gfxinfo | framestats | 逐帧数据 |
公共路径:frameworks/base/core/java/android/view/ 与 frameworks/base/libs/frametimeline/。行号以 r75 检索为准。
如何把超时类型与线程现场对应起来,见 ANR 全类型。