内容提要
本文介绍 Perfetto 现场长 Trace 抓取:先按问题定义证据窗口,再选择 Ring Buffer+STOP trigger、write_into_file 长录制或 clone snapshot 三种模式;用 trigger 封存偶发问题现场,注意权限隔离与未命中收尾;后台运行用 --background-wait,停止后须等文件写完再拉取;Boot Trace 需匹配 ready 点与 buffer 策略;最后用 stats 和 metadata 验收数据可信度。
延伸解读
长 Trace 的核心是证据窗口设计
现场长 Trace 不是把所有开关打开抓一小时,而是先定义问题窗口:问题多久复现、根因在触发前还是后、需要保留多少秒。这决定了用 Ring Buffer+STOP trigger、write_into_file 还是 clone snapshot。UI 偶发卡顿通常只需问题前几十秒,温升降频需分钟级趋势,车机长稳可能跑几小时。窗口设计不当,要么覆盖根因,要么文件过大、开销过高。
三种模式的选择与风险
Ring Buffer+STOP trigger 适合掉帧、ANR 前兆、音频 underrun,但 buffer 太小会覆盖根因,trigger 未命中则无数据。write_into_file 适合几十分钟到数小时趋势,但需关注 I/O 开销和文件上限。clone snapshot 适合调参实验,但依赖设备端 perfetto 支持 --clone-by-name,通常需 Android 14+。不要混成一个“大而全配置”,先按问题选模式再定数据源。
Boot Trace 的边界与 buffer 策略
Android boot tracing 是 Android 13+ 能力,从 /data 挂载后开始,不覆盖 PMIC、bootloader、kernel early boot。buffer 策略需匹配 ready 点:DISCARD 保早期 init/zygote 但可能丢后续 ready 点;RING_BUFFER 保最近窗口但可能覆盖早期事实。90 秒窗口不要用 32MB DISCARD 硬扛,应加大 buffer、缩窄数据源或开启周期写文件,并验收 traced_buf_chunks_discarded。
验收数据可信度与证据包
现场长 Trace 易出现 data loss,分析前先查 trace 覆盖时长和 stats。per-buffer 检查 traced_buf_* 项,RING_BUFFER 下 traced_buf_chunks_overwritten 不一定是错误,但需确认是否覆盖 trigger 前根因。证据包应包含 trace、config、metadata、stats、summary,metadata 记录 trigger 来源、时间、boot id、build 等,summary 用 evidence_grade 分
Q&A
Perfetto 现场长 Trace 有哪几种模式?分别适合什么场景?
有三种模式:1) Ring Buffer + STOP trigger:一直循环记录最近窗口,异常发生后停止,适合掉帧、ANR 前兆、音频 underrun,风险是 Buffer 太小会覆盖根因,trigger 未命中就没有事故现场;2) write_into_file 长录制:周期把 Buffer 写到文件,适合几十分钟到数小时趋势,风险是 I/O 开销和文件过大;3) --clone-by-name snapshot:原始 session 继续跑,按需克隆当前窗口,适合调参、温控、电源策略实验,需要设备端 perfetto 支持 --clone-by-name,Android 上通常要 Android 14(U)+ 或厂商合入的新版 perfetto。
如何用 trigger 抓取偶发问题现场?未命中时怎么处理?
用 trigger 封存偶发问题现场:有权限的一方提前声明 trigger 名称和行为,普通 App 或系统组件只报告事件发生,不能决定抓什么、抓多大、传哪里。STOP trigger 适合根因在触发之前的问题(如慢帧、ANR 前兆、音频 underrun),START trigger 适合事件发生后还要继续观察的问题。trigger 未命中时,按 TraceConfig 官方语义,STOP_TRACING 和 START_TRACING 在 trigger_timeout_ms 到期且没有任何 trigger 命中时,session 会被停止且不返回数据,输出文件是空的,这是设计行为,不是采集失败。脚本要把这种结果显式记录成 trigger_matched=false 并清理空文件,不要把空 trace 当成没有发生问题的证据。
Boot Trace 的 buffer 策略怎么选?DISCARD 和 RING_BUFFER 有什么区别?
Boot Trace 的 buffer 策略要和 ready 点匹配。DISCARD 更容易保住早期 init/zygote 事件,但 buffer 满了会丢后续 ready 点;RING_BUFFER 能保住最近窗口,却可能覆盖早期启动事实。90 秒启动窗口不要用 32MB DISCARD 硬扛,优先加大 buffer、缩窄数据源,或打开周期写文件并验收 traced_buf_chunks_discarded。
后台运行 Perfetto 长 Trace 时,停止后如何安全拉取文件?
停止时不要 kill 后立刻 adb pull,Perfetto 还要把尾部数据写完。至少等 perfetto 进程退出,并确认文件存在且大小稳定后再拉取。脚本可以:发送 kill -INT 后循环检查进程是否退出,然后检查文件大小连续稳定(例如连续 3 次大小相同),再执行 adb pull。如果脚本能控制两端,可以在发 kill 前启动 inotifyd 监听 close_write;设备上没有 inotifyd 时,在进程已退出后用连续大小稳定作为 fallback。文件大小稳定本身不是关闭证明;trigger 未命中、启动失败或文件为空时应有超时并退出,不能无限等待或继续拉取。
现场长 Trace 的写入速率和可录制时长怎么估算?
官方 buffers 文档给出的 Android scheduler tracing 典型值约 1 到 2 MB/s;实际要以当前 preset 实测写入速率为准。可录制秒数按 max_file_size_bytes / 实测写入速率 估算。2GB 上限在 1 到 2 MB/s 下只有约 17 到 34 分钟,撑不到 1 小时;要抓 1 小时,就要缩窄数据源、提高文件上限,或改成 summary/snapshot 策略。log、syscall、page fault、camera/audio、过宽的 Track Event 都可能把写入速率放大一个数量级。
现场证据包里应该包含哪些文件?metadata.json 和 summary.json 有什么作用?
现场证据包至少要能回答这是什么场景、什么时候触发、文件是否完整。建议包含:trace.perfetto-trace、config.pbtxt、metadata.json、stats.sql.txt、log_excerpt.txt、summary.json。metadata.json 建议包含 case_id、trace_config、trigger、trigger_source、trigger_elapsed_realtime_ns、trigger_wall_time、trace_start/end_elapsed_realtime_ns、boot_id、device、build_fingerprint、app_version、battery_percent、thermal_state、upload_reason 等字段,给排查者定位问题窗口、过滤版本、判断环境差异。summary.json 是自动化入口,字段要能直接驱动 triage、上传和留存,不写结论作文,只写机器可读状态,例如 evidence_grade 可以按 A/B/C/D 分级。
分析现场长 Trace 前,如何验收数据可信度?
分析前先看两个验收门:trace 覆盖的时间是否达到预期,stats 是否说明关键数据源可信。先查 trace_start() 和 trace_dur() 确认时长;如果时长不符合预期,先查 trigger_timeout_ms、max_file_size_bytes、后台进程是否被杀、文件是否还没 close、duration_ms 是否按 suspend 语义计算。再跑全局质量检查,并做 per-buffer 检查:traced_buf_* 的 idx 对应 buffer 下标,同时列出全局 flush/config 项。RING_BUFFER 下的 traced_buf_chunks_overwritten 不一定是错误,它通常表示窗口外的旧数据被覆盖,要单独看它是否把 trigger 前根因覆盖掉。如果现场打开 ftrace,还要记录 ftrace clock、可用事件和 setup error。