编辑
2026-04-13
记录知识
0

目录

整体介绍
Producer(数据生产者)
概念
内置traced_probes
外部data source
共享内存机制
Consumer(数据消费者)
概念
常见 Consumer
Tracing Service(traced)
核心职责
1. 会话管理(Session Manager)
2. 缓冲区管理(Buffer Manager)
3. 配置分发(Config Dispatcher)
数据流详解
完整数据流路径
多缓冲区路由
长时间追踪(Long Traces)
进程内模式 vs 系统模式
系统模式(System Mode)
进程内模式(In-Process Mode)
perfetto设计机制
总结
参考资料

在演示perfetto之前,需要介绍一下perfetto的数据处理过程,这样就能够清晰的了解如何抓取trace。

整体介绍

Perfetto 通过生产者消费者模型来抓取数据,其设计的架构可以分为三个层次(消费者/Tracing 服务/生产者):

image.png

  • 消费者:trace_processor_shell或perfetto ui
  • tracing服务: traced
  • 生产者: 自定义的data source

Producer(数据生产者)

概念

Producer 是追踪数据的来源,每个 Producer 可以注册一个或多个 Data Source(数据源)。Producer 通过 UNIX socket 连接到 traced 服务,并在追踪会话期间将数据直接写入共享内存缓冲区。

内置traced_probes

traced_probes 是 Perfetto 最重要的内置 Producer,负责采集系统级数据:

数据源名称功能采集方式
linux.ftrace内核 ftrace 事件读取 tracefs
linux.sys_stats系统统计信息读取 /proc/stat 等
linux.process_stats进程统计信息读取 /proc/[pid]/stat
linux.system_info系统信息读取 /proc/cpuinfo 等

例如

image.png

外部data source

通过配置data source可以自定义一个数据源,例如

image.png

共享内存机制

Producer 与 traced 之间的数据传输使用了共享内存缓冲区(Shared Memory Buffer, SMB)

image.png

工作流程:

  1. Producer 连接到 traced 后,traced 分配一块共享内存
  2. Producer 的每个线程在共享内存中申请一个 Chunk(数据块)
  3. Producer 使用 ProtoZero 库直接在 Chunk 上序列化 protobuf 数据
  4. 当 Chunk 写满后,Producer 通过 IPC 通知 traced 进行提交
  5. traced 将数据从共享内存拷贝到追踪缓冲区

这种设计的优势:

  • 零拷贝序列化:数据直接写入共享内存,避免额外的内存拷贝
  • 线程安全:每个线程独立操作自己的 Chunk
  • 低延迟:无需内核态切换(相比 ftrace 的 trace_marker 方式)

Consumer(数据消费者)

概念

Consumer 是追踪会话的发起者和控制者,负责:

  • 定义 TraceConfig(追踪配置)
  • 启动和停止追踪会话
  • 读取最终的 trace 数据

常见 Consumer

例如有如下消费者

  • perfetto二进制
    bash
    perfetto -c config.pbtx --txt -o trace.perfetto-trace
  • perfetto ui 在线调试
  • record_android_trace 工具
  • Android Framework TraceManager 系统服务

Tracing Service(traced)

核心职责

traced 是整个追踪系统的中枢,主要职责包括:

1. 会话管理(Session Manager)

管理追踪会话的完整生命周期:

image.png

2. 缓冲区管理(Buffer Manager)

traced 管理两种缓冲区:

  • 共享内存缓冲区(SMB):Producer 与 traced 之间的数据通道
  • 追踪缓冲区(Trace Buffer):存储最终 trace 数据的内存区域

追踪缓冲区支持两种填充策略:

protobuf
buffers { size_kb: 65536 fill_policy: RING_BUFFER # 环形缓冲,覆盖旧数据 # fill_policy: DISCARD # 满了就丢弃新数据 }

3. 配置分发(Config Dispatcher)

traced 收到 TraceConfig 后,将其中的 DataSourceConfig 分发给对应的 Producer:

protobuf
data_sources { config { name: "linux.ftrace" # 路由到 traced_probes target_buffer: 0 ftrace_config { ftrace_events: "sched/sched_switch" } } } data_sources { config { name: "track_event" # 路由到 SDK Producer target_buffer: 1 } }

注意:traced 不解码 DataSourceConfig 的内容,只是将原始二进制 blob 转发给匹配的 Producer。这意味着可以引入新的数据源而不需要修改 traced。

数据流详解

完整数据流路径

image.png

多缓冲区路由

不同数据源可以路由到不同的缓冲区,避免高频数据源挤占低频数据源的空间:

protobuf
# 缓冲区 0:高频数据(ftrace),需要较大空间 buffers { size_kb: 131072 fill_policy: RING_BUFFER } # 缓冲区 1:低频数据(进程统计),较小空间即可 buffers { size_kb: 8192 fill_policy: RING_BUFFER } data_sources { config { name: "linux.ftrace" target_buffer: 0 # 路由到缓冲区 0 ftrace_config { ... } } } data_sources { config { name: "linux.process_stats" target_buffer: 1 # 路由到缓冲区 1 process_stats_config { ... } } }

长时间追踪(Long Traces)

对于需要长时间追踪的场景,Perfetto 支持 write_into_file 模式:

protobuf
write_into_file: true file_write_period_ms: 5000 # 每 5 秒刷新一次 buffers { size_kb: 16384 # 只需容纳两次刷新间隔的数据 fill_policy: RING_BUFFER }

在这种模式下:

  • traced 定期将缓冲区数据排空到输出文件
  • 缓冲区只需足够容纳两次写入间隔的数据
  • 可以记录数小时甚至数天的 trace

进程内模式 vs 系统模式

Perfetto SDK 支持两种运行模式:

系统模式(System Mode)

image.png

  • Producer 通过 UNIX socket 连接到系统 traced
  • 可以与系统级数据(ftrace、procfs)一起采集
  • 适合 Android/Linux 系统级追踪

进程内模式(In-Process Mode)

image.png

  • 追踪服务在应用内的专用线程上运行
  • 不依赖系统 traced
  • 适合跨平台或独立应用的追踪
  • 相同的 API,只是初始化配置不同

perfetto设计机制

  1. 服务化解耦:Producer 和 Consumer 通过 traced 解耦,可独立演进
  2. 零拷贝设计:共享内存 + ProtoZero 实现极低开销
  3. 可扩展性:新数据源通过 Producer 注册机制无缝接入
  4. 灵活配置:protobuf 化的配置支持动态能力发现和数据源配置
  5. 多缓冲区:避免不同频率数据源的相互干扰
  6. 双模式支持:系统模式和进程内模式覆盖不同场景

总结

Perfetto 的 Producer-Consumer 架构是其高性能和灵活性的基石。通过共享内存和 ProtoZero 序列化实现极低开销,通过服务化架构实现组件解耦和可扩展性。理解这套架构,是深入使用和定制 Perfetto 的前提。

在下一篇文章中,我们将实战演示如何在 Android 设备上抓取 Perfetto trace,涵盖命令行、UI 以及编程方式的完整操作流程。

参考资料