Android Perfetto 系列 12:Trace 数据流与丢失排查
1 | SELECT name, idx, severity, source, value |
ftrace_setup_errors 的计数在 stats;详情入口与 severity 要按解析器版本区分:v57.2 是 info,失败详情可见于 metadata 的同名项;v58.2 是 notice,详情进入 trace import logs。两版都不能只按 error/data_loss 过滤,跨版本查询应按名称保留该计数。
Buffers and dataflow 文档里有一句很实用的估算:如果总写入速率是 2 MB/s,16 MB central buffer 大约只能保留 8 秒。抓 30 秒、60 秒甚至几分钟时,单靠一个小 central buffer 不够。
这也是很多“录了很久但目标窗口不在 Trace 里”的来源:Ring 覆盖旧数据,Discard 丢弃后续新数字。录制时段写了 60 秒,不代表每个 buffer 都保存了 60 秒统计结果。Trace 文件里的时段轴长度、buffer 能保留的窗口、某类统计结果源的实际覆盖范围,是三件不同的事。
这三件事可以直接用一条 SQL 验收。对每类高频表看最早和最晚事件时间,再和 trace 边界比一比:
1 | SELECT 'trace' AS source, trace_start() AS min_ts, trace_end() AS max_ts |
min_ts 晚于 trace_start() 只能说明这类数据的首条已观测事件更晚,不能单凭差值认定发生过覆盖:数据源晚启动、线程尚未创建、期间没有事件也会如此。要结合 traced_buf_chunks_overwritten、buffer 映射、统计结果源启停与场景 marker 判断;首尾时间也不能排除中间缺段。报告应写已观测范围及覆盖证据,而不是把 trace 总时长当成每个源的完整覆盖时长。
用 stats 给 Trace 做体检
第 11 篇已经讲过 Trace Processor。这里直接用它跑一条 SQL。这条 SQL 适合放进每个分析脚本的开头,它不只查 error / data_loss,也把 central buffer、ftrace setup、FrameTimeline parser/pairing、flush/clock 这类会冲击结论的 info 项一起拉出来。
先分清 stats 的行与统计项定义:它不是完整的能力注册表。kSingle 项可以预置值为 0 的行,kIndexed 项则按本次 Trace 实际写入的 CPU/PID/buffer 索引出现。因此,COUNT(*) = 0 既不能证明该项不受当前版本提供,也不能独立证明采集完整。ftrace_cpu_has_data_loss 和多项 heapprofd_* 在 v57.2、v58.2 都已定义,但没有触发对应记录时可以没有行。判断版本支持应对照 trace_processor --version 对应源码;判断本次数据做工还要结合统计结果源是否采到和目标窗口覆盖。
注意:官方 stats 参考表里的类型写作 kError、kDataLoss、kNotice、kInfo,但 SQL 里的 severity 值是小写的 error、data_loss、notice、info。v58.2 的 ftrace_setup_errors 在 notice 档,v57.2 则为 info;下面按名称保留它,不依赖该项的 severity:
1 | ./trace_processor query trace.perfetto-trace " |
读结果时不要只看“有没有非零”。先把常见项映射到处置决策:
本文由News整理发布,仅供参考。

