3. Perfetto架构与核心概念
Perfetto 并不是一个“打开就能看”的单体工具,而是一套由采集、传输、解析、查询四层组成的可编程追踪平台。理解它的架构,是后续写出高效 SQL、定位复杂性能问题的前提。本节围绕六个核心概念展开:Trace、DataSource、Producer、Consumer、Trace Processor 与 SQL 查询,并用一张架构图把它们串成一条完整的数据链路。
一、核心原理:一条 Trace 的完整生命周期
Perfetto 的设计遵循“采集与解析分离”的原则。设备端只负责把原始数据高效地写入 Trace 缓冲区,真正的解析、建模和查询发生在主机侧的 Trace Processor 中。这样既降低了手机端的开销,又让分析能力可以持续迭代。
整条链路可以概括为:Producer 通过 DataSource 产生数据 → 写入 Trace 缓冲区 → Consumer 读取并保存为 Trace 文件 → Trace Processor 解析为表 → SQL 查询出结论。下面这张图展示了各角色之间的数据流与依赖关系。
二、六个核心概念逐一拆解
Trace(追踪文件)是 Perfetto 的数据载体,本质是一段按 protobuf 编码的二进制流。它自包含、可离线传输,既包含原始事件,也包含采集时的配置信息。一个 Trace 文件可以同时容纳 ftrace、进程统计、堆采样、GPU 计数器等多种数据源,这是它相比传统 systrace 的关键优势。
DataSource(数据源)是“采集什么”的声明。它由名称和配置组成,例如 linux.ftrace 负责内核事件,android.atrace 负责 Android 系统标签,android.heapprofd 负责堆内存采样。DataSource 是 Producer 与采集会话之间的契约:Consumer 在配置中声明需要哪些 DataSource,Producer 按需注册并启动。
Producer(生产者)是设备端真正干活的进程或线程。它向 traced 服务注册自己支持的 DataSource,收到启动指令后开始采集,并把数据写入共享内存缓冲区。常见的 Producer 包括 traced_probes、heapprofd、traced_perf 以及应用内嵌的 SDK。
Consumer(消费者)是采集会话的发起方,负责下发配置、读取缓冲区并保存为 Trace 文件。命令行工具 perfetto 就是最常用的 Consumer,它既可以在设备上运行,也可以在主机上通过 adb 与设备通信。
Trace Processor 是分析引擎,负责把二进制 Trace 解析成结构化的 SQL 表。它内置了 slice、thread、process、counter、sched、ftrace_event 等表,并支持自定义 SQL 函数。所有查询都发生在内存中的 SQLite 实例上,因此速度很快。
SQL 查询是最终的分析手段。用户通过标准 SQL 对表做过滤、聚合、连接和窗口计算,把原始事件转化为可解释的性能结论。
三、方法流程:从采集到查询的实操步骤
下面以采集一段包含调度与频率信息的 Trace 为例,展示完整流程。
# 1. 编写采集配置 config.pbtx
buffers { size_kb: 65536 fill_policy: RING_BUFFER }
data_sources {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "sched/sched_switch"
ftrace_events: "power/cpu_frequency"
atrace_categories: "sched"
}
}
}
# 2. 使用 perfetto 命令行采集(Consumer 角色)
perfetto -c config.pbtx --txt -o /data/misc/perfetto-traces/trace.perfetto-trace
# 3. 拉取到主机
adb pull /data/misc/perfetto-traces/trace.perfetto-trace .
# 4. 用 trace_processor_shell 执行 SQL
trace_processor_shell trace.perfetto-trace -q "
SELECT name, dur, ts
FROM slice
WHERE dur > 5000000
ORDER BY dur DESC
LIMIT 10;
"
这段流程体现了架构的层次:配置声明 DataSource,perfetto 命令作为 Consumer 驱动采集,Trace Processor 加载文件,SQL 完成分析。每一步都可以独立替换或扩展。
四、核心对象对照清单
| 概念 | 所在位置 | 核心职责 | 典型代表 |
|---|---|---|---|
| Trace | 文件 / 内存流 | 承载全部采集数据的自包含载体 | trace.perfetto-trace |
| DataSource | 设备端 | 声明采集内容与参数 | linux.ftrace、android.heapprofd |
| Producer | 设备端 | 注册数据源并写入缓冲区 | traced_probes、heapprofd |
| Consumer | 设备端 / 主机端 | 下发配置、读取并保存 Trace | perfetto 命令行、Perfetto UI |
| Trace Processor | 主机端 | 解析 Trace 并建模为 SQL 表 | trace_processor_shell |
| SQL 查询 | 主机端 | 从表中提取性能结论 | slice、sched、counter 表查询 |
五、案例场景:一次卡顿分析的链路还原
假设用户反馈“滑动列表时偶发卡顿”。分析者首先用 Consumer 采集包含 sched/sched_switch、atrace 和 cpu_frequency 的 Trace。Trace Processor 加载后,SQL 先查主线程的 slice 时长,发现某帧的 doFrame 超过 16ms;再连接 sched 表,发现该线程在关键区间被频繁抢占;最后关联 cpu_frequency 表,确认当时大核频率被限制。整条链路中,Producer 负责采集,DataSource 决定采什么,Consumer 负责保存,Trace Processor 负责建模,SQL 负责把三者串成因果解释。
INCLUDE PERFETTO MODULE 引入官方分析模块,例如 android.binder、android.memory,可以直接复用社区沉淀的查询逻辑,避免重复造轮子。
六、常见误区与复盘
- 把 Producer 和 DataSource 混为一谈:Producer 是进程实体,DataSource 是采集能力的声明。一个 Producer 可以注册多个 DataSource,一个 DataSource 也可能由多个 Producer 提供。
- 认为 Trace 文件只是“日志”:它包含配置、时钟同步、进程元数据等结构化信息,是 Trace Processor 建模的基础,缺失元数据会导致表关联失败。
- 忽略缓冲区策略:RING_BUFFER 会覆盖旧数据,适合短时高频采集;DISCARD 则保留最早数据。选错策略会导致关键区间丢失。
- 直接对原始表做全量扫描:应先用
ts和dur缩小时间窗口,再连接其他表,否则大 Trace 上查询会非常慢。 - 忘记时钟域差异:不同 DataSource 可能使用不同时钟,Trace Processor 会做归一化,但自定义数据源需要显式声明时钟类型。
掌握这六个概念及其数据流关系后,后续学习 Trace 配置、SQL 表结构和具体分析场景时,就能始终清楚“数据从哪里来、经过谁、变成什么、如何被查询”,从而写出更有针对性的分析语句。