3. Perfetto架构与核心概念

Perfetto 并不是一个“打开就能看”的单体工具,而是一套由采集、传输、解析、查询四层组成的可编程追踪平台。理解它的架构,是后续写出高效 SQL、定位复杂性能问题的前提。本节围绕六个核心概念展开:Trace、DataSource、Producer、Consumer、Trace Processor 与 SQL 查询,并用一张架构图把它们串成一条完整的数据链路。

一、核心原理:一条 Trace 的完整生命周期

Perfetto 的设计遵循“采集与解析分离”的原则。设备端只负责把原始数据高效地写入 Trace 缓冲区,真正的解析、建模和查询发生在主机侧的 Trace Processor 中。这样既降低了手机端的开销,又让分析能力可以持续迭代。

整条链路可以概括为:Producer 通过 DataSource 产生数据 → 写入 Trace 缓冲区 → Consumer 读取并保存为 Trace 文件 → Trace Processor 解析为表 → SQL 查询出结论。下面这张图展示了各角色之间的数据流与依赖关系。

Perfetto 架构与数据流 设备端(Android) Producer traced / heapprofd / ftrace DataSource linux.ftrace / atrace 注册 Trace 缓冲区(共享内存) protobuf 编码 · 环形缓冲 · 低开销写入 写入 Consumer perfetto 命令行 / 库 · 读取并落盘 读取 主机端(分析环境) Trace 文件(.perfetto-trace) 自包含 · 可离线分享 · 可复现 传输 Trace Processor 解析 protobuf → 建模为 SQL 表 加载 SQL 查询 slice / thread / counter / sched 等表 查询 采集与解析分离:设备端低开销写入,主机端灵活建模与查询

二、六个核心概念逐一拆解

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 负责把三者串成因果解释。

实用提示:Trace Processor 支持 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 表结构和具体分析场景时,就能始终清楚“数据从哪里来、经过谁、变成什么、如何被查询”,从而写出更有针对性的分析语句。