第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 ./

原因定位:根据现象选择配置跳转路径

下图为从采集参数异常到问题根因的判断路线图:

故障树说明:节点为决策条件,箭头指向对应的调查方向。帮助快速确定配置错误还是设备限制。
命令行采集参数故障树 采集到的 Trace 不完整/无卡顿 缓冲区溢出? 增大 buffer_kb 到 16384 或改用 RING_BUFFER 时长不足? 增加 --time 到 20s 检查 /proc/sys/... 限制 或关闭低优先级数据源 重启 perfetto 服务 或检查 adb 连接状态 操作未落在采集窗口 改用 trigger 模式 检查设备处于 idle 状态 增加事件注入 决策要点 ①优先检查 buffer 是否满(可看 Perfetto UI 启动时的 Buffer 占用率) ②时长不足时,Trace 会完整结束但缺乏卡顿;需确保卡顿操作发生在采集窗口内 ③若设备负载高,减少数据源或提高 buffer

修复动作:参数调优与常见问题处理

  • 缓冲区溢出导致数据丢失:在配置中将 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

预防:标准化采集流程

  1. 建立团队共享的 perfetto_config.pb 模板,包含缓冲区 8MB、8 秒时长、核心数据源。
  2. 在 CI 中加入 adb shell perfetto --config ... --time 30 --out /sdcard/trace.perfetto 步骤,配合 monkey 事件自动触发。
  3. 定期检查设备 /proc/sys/kernel/perf_event_max_sample_rate 是否够高(建议≥10000),否则大 buffer 时 perfetto 可能被抑制。
  4. 对经常出现“buffer overrun”的设备(Android 11 以前),在配置中明确 fill_policy: RING_BUFFER 以避免采集中途停止。
最佳实践:日常摸底采集使用 adb shell perfetto --txt --config - --out /data/local/tmp/trace.perfetto --time 12 <<EOF 直接 inline 配置,避免文件传输步骤。