news 2026/9/18 1:13:53

Perfetto 多机追踪架构深度解析:traced_relay、机器身份与跨内核时钟同步

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Perfetto 多机追踪架构深度解析:traced_relay、机器身份与跨内核时钟同步

Perfetto 多机追踪架构深度解析:traced_relay、机器身份与跨内核时钟同步

【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto

导读

多机追踪(Multi-machine tracing)是 Perfetto 面向复杂软件系统的一项能力:它能把分布在多台操作系统镜像(宿主机与虚拟机、SoC 与协处理器、多台测试机组成的集群)上的事件,录制成一条单一 trace,在一个统一时间轴上呈现并可用 SQL 查询跨机因果关系。本文将基于仓库中的架构文档,结合traced_relaytraced与 Trace Processor 的源码实现,讲清多机追踪"是什么、各部件如何配合"(记录的具体步骤见 Multi-machine recording),读完后你将掌握 relay 转发模型、机器身份(machine_id)机制、跨内核时钟同步原理,以及数据源分发配置等关键实现细节。

问题陈述:单机服务模型为何在多机场景失效

Perfetto 标准的 service model 隐含一个前提:所有 producer、traced服务与 consumer 共享同一个操作系统镜像。它们通过本地 UNIX socket 访问traced,共享同一个 PID 命名空间,并观察同一个CLOCK_BOOTTIME时钟。

一旦某个 producer 跑在另一个内核上,这个前提立即被打破:

  • 没有共享的 filesystem socket——UNIX socket 无法跨内核访问;
  • PID 命名空间相互独立——同一 PID 在不同机器上指代不同进程;
  • boot 时钟起点不同且各自漂移——CLOCK_BOOTTIME的零点因内核而异,无法直接比较。

一种朴素的做法是:在每台机器上各自运行traced,录完再用 merging-traces 事后合并。但这种方式下,跨机器时钟对齐的精度只取决于各机器墙钟同步(或手动提供的偏移量),对任何时间敏感的分析(如跨机调度、RPC 时延)都不够可靠。

Live 多机追踪(live multi-machine tracing)的解决思路是:在录制期间实时测量时钟偏移,且不需要在每台机器上复制 buffer 和 consumer 机制。这正是本文介绍的核心架构。

整体架构:一台 host 的 traced + 所有远程机器的 traced_relay

多机设置中,恰好一台机器运行traced(即 host),其余每台机器运行traced_relay,把 producer 侧 IPC 转发到 host。文档中的架构图如下:

Remote machine Host machine ┌────────────────────────┐ ┌────────────────────────────┐ │ traced_probes │ │ traced --enable-relay- │ │ + other producers │ │ endpoint │ │ │ │ │ ▲ │ │ ▼ (local IPC) │ TCP/vsock │ │ (local IPC) │ │ traced_relay ────────┼──────────────►│ relay endpoint │ └────────────────────────┘ │ ▲ │ │ │ │ │ traced_probes / other │ │ local producers │ │ ▲ │ │ │ (consumer IPC) │ │ perfetto cmdline │ └────────────────────────────┘

关键角色与职责划分:

  • traced(host 侧):通过--enable-relay-endpoint在 producer socket 上额外开放 relay endpoint,接受远程traced_relay连接;
  • traced_relay(远程机器侧):在本地 producer socket 上接受 producer 连接,与 host 交换少量元数据后,把 producer IPC 帧通过TCP 或 vsock代理到 host;
  • consumer(perfetto命令行或 UI 的 WebSocket bridge)永远只与 host 的traced通信。Trace 配置、buffer 所有权、最终读回都集中在单台机器上。

traced_relay 的"刻意轻薄"设计

从 src/traced_relay/ 目录的源码结构看,traced_relay的实现刻意保持最小化:

  • relay_service_main.cc 只是入口,直接调用perfetto::RelayServiceMain()
  • relay_service.h 定义RelayServiceRelayClient两个核心类;
  • socket_relay_handler.h 负责 socket 间的帧转发。

不缓冲 trace 数据、不解析 trace packet、不实现任何 consumer 侧功能——只做透明的 IPC 代理。RelayClient的职责按 relay_service.h 中的注释可分为四步:① 用 client socket name 连接 host(支持如vsock://2:10001这样的 vsock 地址);② 连接后发送SetPeerIdentity消息,让 tracing service 知道本 RelayClient 的机器身份;③ 将 socket 交给RelayIPCClientRelayPortRPC 服务的客户端实现);④ 任何 socket 错误都会通过OnErrorCallback通知上层(RelayService)以便重试连接。此外RelayClient还承担与 host 的时间同步职责,其阶段状态机(Phase::CONNECTING / PING / UPDATE)与SendSyncClockRequest()方法体现了下文将介绍的时钟同步流程。

这种设计带来的直接好处是:buffer 分配、clock snapshot 发出、consumer 读回等复杂逻辑只在 host 上存在一份,远程机器上几乎零状态。

机器身份:SetPeerIdentity 与 machine 表

traced_relay首次连接 host 时,会发送一条SetPeerIdentity消息,其中包含machine_id_hint。该 hint 的生成逻辑在 relay_service.cc 的RelayService::GetMachineIdHint()中:

  • 首选读取/proc/sys/kernel/random/boot_id(Linux 上可用时);
  • 否则回退到uname(2)的哈希加上一个 bootup 时间戳来源(get_pseudo_boot_id()逻辑)。

因此该 hint 对同一内核的多次重连是稳定的,但在不同内核之间互不相同

host 的traced会把每个唯一 hint 映射为一个小整数MachineId,并给从该 relay 到达的每个TracePacket盖上这个标记(即TracePacket上的machine_id字段)。导入时,Trace Processor 为每台机器在machine中物化一行。其表结构定义见 metadata_tables.py:

ColumnDescription
idTrace-Processor 分配的机器 ID。host 恒为0
raw_id来自 trace packet 的原始机器标识(host 为0,远程机器非零)。
sysname,release,version,arch该机器的uname(2)字段。
num_cpus该内核可见的 CPU 数量。
system_ram_bytes,system_ram_gb总内存。
android_build_fingerprint,android_device_manufacturer,android_sdk_version仅 Android 机器填充。

跨机数据切片:凡是带每 CPU 或每线程维度的表(threadcpugpu_counter_track等),都携带可空的machine_id列,因此可以用 SQL 按机器切分数据。例如cpu表通过ucpu(全局统一的 CPU 编号)关联到具体机器,其machine_id列可参与 join。目前 UI 对每机 track 的支持仍在演进中,所以machine_idjoin 是回答跨机问题最可靠的方式

跨机器时钟同步:轻量 ping 协议与时钟图

每台远程机器有自己的CLOCK_BOOTTIME,其 producer 写入的时间戳不能与 host 直接比较。traced_relay通过轻量 ping 协议与 host 的 relay endpoint 交互:发送并接收带时间戳的消息,从而估算每台机器的时钟偏移与往返时间(RTT)。host 将每台远程机器的成对ClockSnapshotRemoteClockSyncpacket 的形式写入 trace。

从 clock_tracker.cc 的源码可以看出这一机制在导入端的落点:时钟 ID 通过ClockId::Qualify(clock_id, machine_id_, ...)进行机器限定(machine-qualified),使不同机器的同名时钟成为时钟图中的独立节点;远程机器的时钟快照被折叠进同一个时钟图中。其后续处理完全复用 Clock Synchronization 中已有的单机机制:

  • Trace Processor 把跨机偏移折叠进它本就要为CLOCK_REALTIMECLOCK_MONOTONIC等构建的时钟图;
  • 导入时把每个事件解析到单一全局 trace 时钟
  • 数据源无需任何额外工作

值得注意的是,同一个时钟图同样支撑 post-hoc trace merging(事后合并)——区别只在于跨机边的来源:live 录制来自 ping 协议,事后合并来自墙钟 rendezvous 或 perfetto_manifest 清单文件。

数据源分发:trace_all_machines 与 machine_name_filter

默认情况下,traced只把数据源分发给 host 机器上的 producer。要从远程机器采集数据,consumer 的TraceConfig必须显式选择,二选一:

  1. 全局trace_all_machines: true
  2. 按数据源DataSource.machine_name_filter

若两者都不设置,远程机器上的traced_probes虽然仍会注册、并作为machine表的一行出现,但永远不会被分配请求的数据源,因此不会有任何事件流出。对应 proto 定义见 trace_config.proto:

  • DataSource.machine_name_filterrepeated string machine_name_filter = 4)按机器名过滤。机器名的确定优先级为:PERFETTO_MACHINE_NAME环境变量 → Android 系统属性persist.traced_relay.machine_nameuname -s的 utsname sysname(如Linux)。字面量"host"是运行traced那台机器的同义词
  • trace_all_machinesoptional bool trace_all_machines = 43):为true时,远程 producer(通过traced_relay连接的机器)中的数据源默认被匹配;为false(默认)时只匹配 host。显式设置的machine_name_filter优先级更高。

版本兼容注意事项trace_all_machinesperfetto v54引入;v54 之前的版本默认匹配所有机器。文档建议,要跨过这个版本边界保持兼容,要么把该字段设为true,要么给所有数据源显式设置machine_name_filter

一个容易踩的坑:同一内核无法冒充"两台机器"

同一内核上的两个 producer 即使分别注册,也不能当作"两台机器"用于测试。原因在于:两个traced_probes实例会竞争同一个/sys/kernel/tracing/ring buffer,而 per-CPU 事件会被任意切分到两个machine_id之间——trace 看起来有效,实际却静默撕裂(silently torn)。多机设置必须需要两个内核(两台机器、host 加 VM、拥有各自内核命名空间的独立容器等)。

限制与约束

多机架构文档明确列出了以下约束:

  • traced_relay不能与traced同机运行——两者都要绑定本地 producer socket。设置中每台机器要么运行traced(host),要么运行traced_relay(其余所有机器);
  • 每台远程机器必须有到达 host relay endpoint 的网络路径(TCP 或 vsock)
  • 跨机器时钟对齐精度取决于 ping 协议对偏移的测量;粗略对齐的墙钟(NTP 等)有助于首批 snapshot,但并非严格必需
  • UI 的每机 track 渲染仍在演进,当前按机器切分跨机数据的权威方式仍是查询machine表与machine_id列的 SQL。

实战速览:两台 Linux 主机的多机录制

架构文档聚焦"是什么"与"如何拼装",具体的逐步操作记录见 Multi-machine recording。这里给出核心流程梗概(host运行tracedguest运行traced_relay):

  1. host 启动traced并监听 TCP--enable-relay-endpoint让该 socket 同时接受 relay 连接):
    PERFETTO_PRODUCER_SOCK_NAME=0.0.0.0:20001 \ tracebox traced --enable-relay-endpoint

    若还需保留本地 AF_UNIX producer socket,可同时列出两个 socket 并用更窄的--enable-relay-endpoint-on指名哪个 socket 承载RelayPort(注意该 flag 只是从PERFETTO_PRODUCER_SOCK_NAME中已列出的 socket 里选择,不会引入新端点)。

  2. host 启动traced_probesPERFETTO_PRODUCER_SOCK_NAME=127.0.0.1:20001 sudo -E tracebox traced_probessudo -E保留环境变量以获取 ftrace 权限)。
  3. guest 启动traced_relayPERFETTO_RELAY_SOCK_NAME=<host-ip>:20001 tracebox traced_relay,成功时输出形如Started traced_relay, listening on /tmp/perfetto-producer, forwarding to <host-ip>:20001的启动行。
  4. guest 启动traced_probes:直接sudo tracebox traced_probes(无环境变量时自动连接默认 UNIX socket,即traced_relay监听的路径)。
  5. host 侧用显式TraceConfig录制:多机追踪要求显式配置(tracebox perfetto -t 10s ...简写只会录 host 本机)——配置中必须包含trace_all_machines: true或各数据源的machine_name_filter,例如:
    buffers { size_kb: 32768 fill_policy: RING_BUFFER } trace_all_machines: true data_sources { config { name: "linux.ftrace" ftrace_config { ftrace_events: "sched/sched_switch" } } } duration_ms: 10000

    随后执行tracebox perfetto --txt -c config.pbtx -o trace.pftrace

  6. 验证两台机器都在 trace 中:在 SQL 查询视图中执行SELECT id, raw_id, sysname, release, arch, num_cpus FROM machine;,期望两行,id = 0恒为 host;再通过cpu表 join 按机器统计事件数:
    SELECT cpu.machine_id, COUNT(*) AS num_events FROM ftrace_event JOIN cpu USING (ucpu) GROUP BY cpu.machine_id;

常见故障排查要点:machine表只有一行通常是连通性问题(检查端口可达、防火墙、host 是否绑定了0.0.0.0而非127.0.0.1);traced_relay立即退出并打印用法说明PERFETTO_RELAY_SOCK_NAME未设置。

总结与下一步

多机追踪架构的核心设计哲学可以概括为:让一台 host 承担全部状态(buffer、consumer、配置),让远程机器只做"轻薄"的 IPC 转发与时钟测量,再通过SetPeerIdentity建立机器身份、通过 ping 协议把跨内核时钟偏移折叠进既有的时钟图,最终在 Trace Processor 侧得到一张带machine_id维度的统一时间轴。这与 trace-processor-architecture 中"导入期统一时钟图"的设计一脉相承。

后续深入方向:

  • Multi-machine recording——两台 Linux 主机录制多机 trace 的完整逐步演练;
  • Trace merging——事后把独立录制的 trace 合并进同一多机模型;
  • Clock Synchronization——跨机偏移在导入时折叠进的单机时钟同步图;
  • machine表参考——由SetPeerIdentity填充的表完整 schema。

【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 1:13:50

WebSocket技术解析与实时通信实战

1. WebSocket 技术解析&#xff1a;从 HTTP 瓶颈到实时通信革命在传统的 Web 开发中&#xff0c;我们经常会遇到这样的需求&#xff1a;聊天消息实时显示、股票行情即时更新、多人协作文档同步编辑...这些场景都需要服务器能够主动向客户端推送数据。然而基于 HTTP 协议的请求-…

作者头像 李华
网站建设 2026/9/18 1:12:58

PDF教学大纲结构化抽取:文本层解析、学时对账与目标分级落库

简介&#xff1a;这份《临床医学五年制法医学课程教学大纲》面向临床医学专业五年制本科生及授课教师&#xff0c;可用于课前了解课程框架、复习考试或在教学中对照学时安排备课。大纲围绕法医学的基本理论、基本知识与基本技能展开&#xff0c;覆盖绪论、死亡与尸体现象、机械…

作者头像 李华
网站建设 2026/9/18 1:07:07

AI漫剧制作全流程拆解:从零基础到接单的实战教程

AI漫剧这四个字,最近在短视频平台和各类接单群里出现的频率越来越高,有朋友一上来就问"现在做这个到底还能不能赚钱""零基础是不是真的能学会"。我年初开始系统研究AI漫剧制作,当时纯粹好奇AI生成图片能不能变成连贯的剧情短视频,结果一跑通就发现,这已经是…

作者头像 李华
网站建设 2026/9/18 1:03:39

印刷机递纸机构运动仿真与多软件协同设计平台

简介&#xff1a;本资源是面向机械类本科生的《机械原理》课程设计专项资料&#xff0c;聚焦平台印刷机主传动机构的设计与分析&#xff0c;适用于机械设计制造及其自动化等专业学生完成课程设计、课程报告及答辩准备。资料以1份761KB的Word文档&#xff08;.doc&#xff09;形…

作者头像 李华
网站建设 2026/9/18 1:01:30

HWSD v2.0土壤数据库:技术解析与应用实践

1. 项目概述&#xff1a;HWSD v2.0土壤数据库的核心价值全球土壤数据一直是农业、生态研究和气候变化模拟领域的基石性资源。HWSD v2.0作为目前分辨率最高的公开土壤数据库之一&#xff0c;其1km网格精度和12项核心土壤属性的组合&#xff0c;解决了传统土壤数据碎片化、分辨率…

作者头像 李华
网站建设 2026/9/18 0:59:29

YuE模型实战:AR-NAR混合Transformer部署与微调指南

1. 项目概述&#xff1a;从“YuE”到可复现的AR–NAR MoT模型实践路径第一次在Hugging Face Spaces里看到标着“YuE”的模型卡片时&#xff0c;我下意识以为是某个新出的中文LLM缩写——毕竟最近带拼音首字母的模型名太多了。但点开模型页&#xff0c;发现作者署名是“microsof…

作者头像 李华