Perfetto 下一代追踪工具:安装、配置、使用技巧
Perfetto 不是什么新玩具,而是 Google 官方钦定的下一代全平台追踪套件。说白了,就是替换 systrace 的。我最早接触它是在 2019 年,当时还被它的复杂配置劝退过 —— 确实比 systrace 多几个步骤。但用顺了之后,我只能说一句:真香。
1. 安装与基础配置
Perfetto 的安装分两大块:
- 服务端(跑在手机/模拟器上):
perfetto可执行文件 - 客户端(跑在电脑上):
traceconv转换器 +trace_processor分析引擎
手机端其实不需要额外安装,因为 Perfetto 已经集成在 Android 9+ 的 system 分区里了。我个人习惯先用 adb 确认一下它的版本:
adb shell perfetto --version
如果返回一串数字(比如 v21.0),就说明环境就绪。低于 Android 9 的机型,需要手动 push 二进制文件。我有个项目还在跑 Android 8.1,只好用旧版 Perfetto 或者干脆回退到 systrace。
电脑端配置更简单。我推荐直接下载官方集成的 all-in-one 包:
# macOS/Linux
curl -LO https://get.perfetto.dev/traceconv
chmod +x traceconv
# 或者用 pip 安装 python 版本的 trace_processor
pip install perfetto
在 Windows 上直接用 WSL 或者下载预编译的 exe 都行 —— 不过我踩过坑,Windows 的路径分隔符很容易炸,所以建议统一用 WSL。
ptrace,一键抓取加转换。
3. 抓取 Trace 的三种姿势
Perfetto 支持三种抓取模式,场景不同用不同的方式。我自己总结了一个对照表:
| 模式 | 适用场景 | 耗时 | 数据精细度 |
|---|---|---|---|
| 命令行 + 配置文件 | 日常性能问题复现 | 几分钟 | 中 |
| Web UI(chrome://tracing) | 快速验证、新手入坑 | 30秒 | 低 |
| SDK 注入(代码内) | 精准打点、自定义事件 | 几小时(开发) | 极高 |
我平时 80% 的情况用第一种。写一个 .pbtxt 配置文件,指定缓冲区大小(4MB~64MB)、需要追踪的 atrace 类别(比如 am, wm, gfx, input)、以及 ftrace 事件(比如 sched_switch, cpu_frequency)。
buffers: {
size_kb: 65536
fill_policy: RING_BUFFER
}
data_sources: {
config {
name: "android.packages_list"
}
}
data_sources: {
config {
name: "linux.ftrace"
ftrace_config: {
ftrace_events: "sched/sched_switch"
ftrace_events: "power/suspend_resume"
ftrace_events: "power/cpu_frequency"
atrace_apps: "com.example.myapp"
}
}
}
然后直接用命令抓 10 秒:
adb shell perfetto -c /data/local/tmp/trace_config.pbtxt \
-o /data/local/tmp/trace.perfetto-trace \
--txt -t 10s
嗯,这里要注意——缓冲区的 fill_policy 如果设成 RING_BUFFER,超时之后的旧数据会被新数据覆盖。我曾经因为这个漏掉了最关键的几帧,后来才改成 DISCARD 确保保留启停时刻的数据。
3. Trace 分析与关键技巧
抓回来的是 .perfetto-trace 文件,直接用 traceconv 转成 UI 能打开的 JSON,或者用 trace_processor 做 SQL 查询。
# 转成 JSON(供 Perfetto UI 使用)
traceconv json trace.perfetto-trace trace.json
# 使用 SQL 模式分析(我更喜欢这种方式,精确)
trace_processor --analyze trace.perfetto-trace
转到 SQL 模式后,最常用的几个查询:
- 查看长帧分布:
SELECT ts, dur FROM slice WHERE name='Choreographer#doFrame' AND dur > 16666666; - 定位谁占了主线程:
SELECT thread.name, SUM(dur) FROM thread_state JOIN thread USING(utid) WHERE cpu != -1 GROUP BY thread.name; - 检查 CPU 频率是否被限:
SELECT * FROM counter JOIN counter_track ON counter.track_id = counter_track.id WHERE counter_track.name LIKE 'cpufreq%';
我曾经用第二条 SQL 抓到一个第三方 SDK 在渲染线程里同步写日志,差点气吐血。因为 Perfetto 是系统级追踪,连 kernel 的线程上下文切换都能看到,那些隐藏极深的卡顿根本藏不住。
atrace_apps 参数抓取所有应用,这会把系统拖得更慢,导致 trace 失真。正确的做法是:在抓取前确定要分析的进程名,目标清晰。
我还推荐一个非常实用的小技巧:使用 long_trace 模式。普通 trace 受限于内存,最多抓 30 秒左右;但 Perfetto 支持将数据实时写入文件(比如写到 sdcard),这样就可以连续追踪 10 分钟、甚至更久。你只需要在配置文件中添加:
write_into_file: true
file_write_period_ms: 5000
适合追踪偶现的 ANR 或者卡顿 —— 不过要提前做好该文件会占用几百 MB 到数 GB 的心理准备。
4. Perfetto 知识体系总览
下面这张图我花了一点时间梳理,基本覆盖了 Perfetto 的使用全流程。你看一眼就能明白工具链的上下游关系。
整个流程一目了然:配置 → 抓取 → 转换 → 分析 → 结论。我自己更喜欢在 SQL 里直接查,因为可视化虽然直观但容易淹没在海量事件里。你如果刚开始接触,建议先用 Web UI 观察整体走势,再逐步深入到 SQL 分析。