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。

我的习惯:把 traceconv 和 adb 同时加入 PATH,然后写个 alias 叫 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 模式后,最常用的几个查询:

  1. 查看长帧分布:
    SELECT ts, dur FROM slice WHERE name='Choreographer#doFrame' AND dur > 16666666;
  2. 定位谁占了主线程:
    SELECT thread.name, SUM(dur) FROM thread_state JOIN thread USING(utid) WHERE cpu != -1 GROUP BY thread.name;
  3. 检查 CPU 频率是否被限:
    SELECT * FROM counter JOIN counter_track ON counter.track_id = counter_track.id WHERE counter_track.name LIKE 'cpufreq%';

我曾经用第二条 SQL 抓到一个第三方 SDK 在渲染线程里同步写日志,差点气吐血。因为 Perfetto 是系统级追踪,连 kernel 的线程上下文切换都能看到,那些隐藏极深的卡顿根本藏不住。

避坑指南:不要在 release 包上直接用 Perfetto 的 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 的使用全流程。你看一眼就能明白工具链的上下游关系。

Perfetto 工具链总览 ① 数据抓取 命令行配置(.pbtxt) Web UI 配置 SDK 自定义 .perfetto-trace 原始文件 traceconv 转 JSON trace_processor SQL Perfetto UI 可视化 自定义 SQL 脚本分析 性能报告 / 卡顿归因 / ANR 根因 📌 核心原则 • 配置文件控制数据源粒度 • 缓冲区大小决定数据完整性 • SQL 分析比可视化更精准

整个流程一目了然:配置 → 抓取 → 转换 → 分析 → 结论。我自己更喜欢在 SQL 里直接查,因为可视化虽然直观但容易淹没在海量事件里。你如果刚开始接触,建议先用 Web UI 观察整体走势,再逐步深入到 SQL 分析。

一句话总结:Perfetto 是性能调优的「显微镜」,能让你看见从 Java 堆栈到 kernel 调度的每一个细节。别怕学习曲线,它值得你投入。