第3章:使用命令行采集 Trace——adb shell perfetto 命令、配置参数与时长控制
现象识别:当 GUI 采集工具(如 Android Studio Profiler、Perfetto UI 中的“Record”按钮)无法满足以下场景时,必须改用命令行采集:
- 需要精确控制缓冲区大小(默认 256KB 可能溢出导致数据截断);
- 需要在非交互式环境(CI/CD、adb shell 脚本)自动采集;
- 需要采集系统级追踪(如 kernel、hardware 模块),GUI 仅暴露部分开关;
- 需要长时间后台采集(超过 GUI 限制的 30 秒);
- 设备未连接网络,无法使用 Perfetto UI 的云端调度。
数据采集:adb shell perfetto 核心命令
命令行采集的核心工具是设备端的 perfetto 可执行文件,通过 adb 远程执行。基本调用语法:
adb shell perfetto [ --config <config.pb> | --txt --config <config.textproto> ] [ --out <trace_file> ] [ --time <duration_secs> ]
配置参数详解
配置通过 Protobuf 格式(.pb)或文本格式(.textproto)指定。下面是最常用的参数及故障排查价值:
| 参数 | 说明 | 典型值 / 排查规则 |
|---|---|---|
buffers | 定义环形缓冲区数量与大小 | 主线程卡顿建议至少 4MB;若出现“buffer overrun”警告,增加至 8MB+ |
data_sources | 开启的跟踪数据源列表 | 排查主线程卡顿必开:linux.ftrace(调度/CPU频率)、android.sched(线程调度)、android.surfaceflinger(帧绘制)、android.input(输入事件) |
duration_ms | 采集时长(毫秒) | 建议 10000(10 秒),覆盖一次完整的点击→渲染→返卡 |
file_write_period_ms | 写入间隔(默认 0 即一次性写入) | 长采集设为 2000 以防设备写满内存 |
flush_period_ms | 强制刷出缓冲区周期 | 设为 5000 可减少丢失尾部事件 |
常见陷阱:
- 未设置
--time时,perfetto 会一直运行直到收到 Ctrl+C;脚本中务必指定时长,否则超时后进程不会自动停止。 - 输出路径
--out如果指定为/data/local/tmp/trace.perfetto,采集后需用adb pull拉到本地。 - 缓冲区大小不足时,Perfetto 不会报错,只会静默丢弃旧数据,导致 Trace 中关键卡顿时刻“断片”。
时长控制策略
选择合适的采集时长直接影响排查成功率:
- 短采集(3~5 秒):用于复现特定操作(如启动崩溃),需提前操作,然后立即触发希望截获的卡顿。
- 中采集(10~15 秒):最常用。用户操作后等待 2 秒,然后开始采集 8 秒,捕捉从点击到卡顿消失的全周期。
- 长采集(60 秒+):用于偶发卡顿,需配合
trigger_perfetto主动触发或循环脚本。
配置示例(文本格式,保存为 config.textproto):
buffers {
size_kb: 8192 # 8MB
fill_policy: RING_BUFFER
}
data_sources {
config {
name: "linux.ftrace"
target_buffer: 0
}
}
data_sources {
config {
name: "android.sched"
target_buffer: 0
}
}
duration_ms: 12000
file_write_period_ms: 2000
flush_period_ms: 5000
通过 adb 发送并采集:
adb push config.textproto /data/local/tmp/
adb shell perfetto --txt --config /data/local/tmp/config.textproto \
--out /data/local/tmp/trace.perfetto --time 12
adb pull /data/local/tmp/trace.perfetto ./
原因定位:根据现象选择配置跳转路径
下图为从采集参数异常到问题根因的判断路线图:
故障树说明:节点为决策条件,箭头指向对应的调查方向。帮助快速确定配置错误还是设备限制。
修复动作:参数调优与常见问题处理
- 缓冲区溢出导致数据丢失:在配置中将
buffers[0].size_kb调整为 16384(16MB),并将fill_policy设为RING_BUFFER(循环覆盖旧数据保留最新)。 - 采集时长过长导致文件超大:开启
compress: true(默认支持 gzip),文件大小可缩小 3~5 倍;或增加file_write_period_ms间隔。 - Perfetto 未启动或权限不足:针对非 root 设备,执行
adb shell setprop persist.traced.enable 1并重启 traced 服务。 - Trace 文件无法打开:检查
--out路径是否在可写目录(如/data/local/tmp/),然后adb pull到本地。
复测
执行以下验证清单:
| 检查项 | 预期结果 | 验证命令 |
|---|---|---|
| 采集时长准确 | --time 10 历时约 10~11 秒 | time adb shell perfetto ... |
| 文件完整 | Perfetto UI 打开后无“Truncated”警告 | 拖入 ui.perfetto.dev 检查 |
| 主线程卡顿可见 | Trace 中主线程 slice 出现 Janky 标签 | 搜索“Janky”或查看 FrameTimeline |
预防:标准化采集流程
- 建立团队共享的
perfetto_config.pb模板,包含缓冲区 8MB、8 秒时长、核心数据源。 - 在 CI 中加入
adb shell perfetto --config ... --time 30 --out /sdcard/trace.perfetto步骤,配合 monkey 事件自动触发。 - 定期检查设备
/proc/sys/kernel/perf_event_max_sample_rate是否够高(建议≥10000),否则大 buffer 时 perfetto 可能被抑制。 - 对经常出现“buffer overrun”的设备(Android 11 以前),在配置中明确
fill_policy: RING_BUFFER以避免采集中途停止。
最佳实践:日常摸底采集使用
adb shell perfetto --txt --config - --out /data/local/tmp/trace.perfetto --time 12 <<EOF 直接 inline 配置,避免文件传输步骤。