Perfetto 命令行分析实战指南:用 trace_processor 查询、复用会话、合并与转换 Trace
【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto
本篇指南聚焦 Perfetto 项目中最常用的命令行分析工作流:以trace_processor为核心工具,覆盖从获取二进制、运行 SQL 查询、通过后台会话避免重复解析、合并多条 trace、导出解析结果以及转换 trace 格式的完整实操链路。读完本文,你将能够脱离 UI 在 shell 中高效完成 trace 的查询、批处理、合并与格式互转,并将相关命令直接嵌入脚本与 CI 流程。
获取 trace_processor 二进制
trace_processor是 Perfetto 提供的命令行分析入口。获取方式很简单:
curl -LO https://get.perfetto.dev/trace_processor chmod +x ./trace_processor这是一个精简的 Python 包装脚本(约等于仓库中 tools/trace_processor 的自动生成版本),首次运行时才会按你的平台下载并缓存对应的原生二进制trace_processor_shell。从该脚本源码可见(tools/trace_processor),它内置了一份平台清单,覆盖mac-amd64、mac-arm64、linux-amd64、linux-arm、linux-arm64、android-arm、android-arm64、android-x86、android-x64与windows-amd64,每个条目都带有file_size与sha256校验和。
下载后的原生二进制缓存位置为~/.local/share/perfetto/prebuilts/,文件名内嵌了 SHA-256 短哈希,因此同一机器上可以并存多个版本的 trace processor 而互不干扰。下载完成后会校验 SHA-256,校验失败会直接报错,保证缓存文件可信。Windows 平台使用curl.exe -LO https://get.perfetto.dev/trace_processor,并通过python trace_processor ...运行(Python 3 是运行包装脚本的必要条件,curl在 Windows 10 及以后自带)。更多安装细节与 shell 用法参见 Trace Processor 文档。
提示:trace 参数同样支持
http(s)://URL 或 Perfetto UI 分享链接(形如https://ui.perfetto.dev/#!/?s=<hash>),工具会下载并在本地~/.cache/perfetto/下缓存。
运行 SQL 查询:query 子命令
query子命令加载一条 trace,执行一个或多个以;分隔的 SQL 语句,并将每个结果集以CSV形式打印到 stdout(结果集之间以空行分隔,且所有字符串值都会加引号,因此分隔符无歧义)。基本用法:
# 内联 SQL。 trace_processor query trace.pftrace "SELECT ts, dur, name FROM slice LIMIT 5" # 从文件读取 SQL(-f - 表示 stdin),是脚本场景的推荐形式。 trace_processor query -f queries.sql trace.pftrace # 通过管道把 SQL 喂给 stdin。 cat queries.sql | trace_processor query trace.pftrace从实现看(query_subcommand.cc),SQL 的来源按优先级依次是:位置参数 >-f FILE> stdin(当 stdin 不是 TTY 时自动读取)。如果三条路径都没有提供 SQL,命令会报错退出。
query的常用标志(CLI 参考):
--remote ADDR:不再加载本地 trace,而是连到一个已加载好 trace 的后台会话(见下节);ADDR可以是会话名、*.sock或绝对 socket 路径,也可以是host:port。此模式下不再传 trace 文件位置参数。-f, --query-file FILE:从文件读取 SQL;传-表示从 stdin 读取。-i, --interactive:查询执行完毕后进入交互式 REPL。-W, --wide:以双倍列宽打印结果。--perf-file FILE:把 trace 加载耗时与查询耗时写入该文件。
源码中还有一个值得注意的行为(query_subcommand.cc):当一次query调用解析 trace 耗时超过约 1 秒时,工具会在 stderr 打印提示,建议改用会话复用方式避免每次重复解析——这正是下一节要讲的核心优化手段。
避免重复解析:后台会话(sessions)
解析 trace 是成本最高的环节(大型 trace 需要数十秒),而一次普通的query调用每次都会重新解析。当你要对同一条 trace 执行多条查询时,正确的做法是:先把它加载到一个有名字的后台会话中,然后用--remote指向该会话:
# 1. 将 trace 加载进后台会话(每条 trace 只做一次)。 trace_processor server unix --name mysession --daemonize trace.pftrace # 2. 查询热会话:不传 trace 路径,不重新解析。 trace_processor query --remote mysession \ "SELECT ts, dur, name FROM slice LIMIT 10" # 3. 处理完 trace 后停止会话。 trace_processor server kill mysession会话状态在多次--remote调用之间持久保留:某次调用中CREATE PERFETTO TABLE或INCLUDE PERFETTO MODULE建立的东西,下一次调用仍然可见,行为与在同一个交互式 shell 内完全一致。因此,把中间结果物化成 PerfettoSQL 表,可以在跨调用之间反复复用。空闲会话会在30 分钟后自动回收。
实现与原理
从server子命令的实现看(server_subcommand.cc),server unix模式通过 AF_UNIX socket 提供服务:
--name NAME指定会话名(默认自动生成),会话名必须匹配[A-Za-z0-9][A-Za-z0-9_-]*;--path PATH指定显式 socket 路径,与--name互斥;相对路径会被转为绝对路径(因为守护化时进程会chdir到/);--daemonize让进程转入后台运行(unix 模式、仅 POSIX);--idle-timeout auto|DUR控制空闲回收:auto对 unix 模式默认 30 分钟、对 http 模式默认永不回收;也可显式写30m、90s这类时长,0/never表示禁用。代码中 unix 模式默认值即30 * 60 * 1000毫秒(server_subcommand.cc)。--idle-start auto|orphaned|last-query控制空闲时钟从何时起算(默认auto,即 owner-aware)。
server kill的实现(server_subcommand.cc)通过 socket 旁的 pid 文件定位进程并发送 SIGTERM(Windows 下使用TerminateProcess);如果 pid 文件是崩溃残留的僵尸状态会被清理并报错。HTTP 模式的 kill 不被支持,官方建议用 Ctrl-C 或--idle-timeout停止。
需要注意的两点
- 配置 trace 加载行为的标志(
--full-sort、--add-sql-package等)应放在server unix调用上;query --remote会拒绝这些标志。 --remote同样适用于interactive与summarize,因此你可以直接在一个已热的会话上进入 REPL,或对它执行汇总。
query的--remote走的是与 Perfetto UI 相同的 TraceProcessor RPC 接口,底层 RPC 线格式定义在 trace_processor.proto。会话命名、socket 路径与空闲超时调优的完整参考见 trace-processor-cli.md 的 server 一节。
合并多条 trace:util merge
要把多条 trace 文件当作一条来分析(例如两台设备各自录制的 trace,或一条系统 trace 加一条应用内 trace),把它们打包进一个归档即可。对于常见情形(时钟已经可以对齐的 trace),无需任何配置:
trace_processor util merge -o merged.tar trace1.pftrace trace2.pftrace trace_processor query merged.tar "SELECT count(*) FROM slice"util merge会写出一个TAR 归档,Trace Processor 打开它时视作一条合并后的 trace,并会试运行(dry-run)结果,若 trace 无法干净合并会给出警告(--strict会把警告升级为硬错误,适合 CI 场景)。任何包含 trace 文件的 ZIP 或 TAR 归档都能以同样的方式打开,所以即使没有trace_processor依赖,你也可以自己打包:tar cf merged.tar trace1.pftrace trace2.pftrace。
切勿用cat直接拼接文件来"合并",那不是合并,参见 Trace merging 概念文档。
当需要控制 trace 的组合方式时(如保持各设备数据分离、对齐未同步的时钟、给机器命名),可以通过--manifest manifest.json传入 trace 清单(manifest),或自行把 manifest 打进归档。详细说明(含如何验证合并把每个事件都放到了时间线上)见 命令行合并 trace 指南。
什么情况不需要配置
Trace Processor 能够关联各文件时钟时,无需额外配置,典型场景:
- 同一设备录制的 trace:同一 boot 期间的录制共享时钟域(如
BOOTTIME),带ClockSnapshot数据包的文件会显式关联各时钟域。 - 不同设备但墙钟已同步:
REALTIME被假定为所有机器一致(实践中即 NTP),因此同时刻录制的两台手机 trace 会自动对齐到真实墙钟位置。 - 已预置 machine id 的 trace:用 machine id 初始化的 SDK producer 会为其写入的每个数据包打标,合并后各文件数据自动归属不同机器,无需 manifest(C++ 侧通过
perfetto::TracingInitArgs::machine_id设置,C SDK 对应PerfettoProducerBackendInitArgsSetMachineId())。
如果既没有共享时钟域,REALTIME也无法确定文件位置,事件会被丢弃而不是猜测——这时就需要 manifest 了。
用 manifest 精确控制合并
perfetto_manifest是加入归档的 JSON 文件,用于控制 Trace Processor 如何解读归档内文件。举两个核心场景:
保持两台设备数据分离(命名 machine):
{ "perfetto_manifest": { "version": 1, "files": [ {"path": "device_a.pftrace", "machine": {"name": "device-a"}}, {"path": "device_b.pftrace", "machine": {"name": "device-b"}} ] } }trace_processor util merge -o merged.tar --manifest manifest.json \ device_a.pftrace device_b.pftrace trace_processor merged.tar把无时钟的 trace 钉到系统 trace 上(Chrome JSON、Gecko、Instruments 这类没有绝对时钟的格式):
{ "perfetto_manifest": { "version": 1, "trace_time": {"clock": "BOOTTIME"}, "files": [ {"path": "system_trace.pftrace"}, { "path": "app_trace.json", "clocks": { "sync_to": {"file": "system_trace.pftrace", "clock": "BOOTTIME"}, "offset_ns": 100000000 } } ] } }offset_ns的语义:在同一时刻,源文件时钟读数为 T 时,参考时钟读数为 T +offset_ns,因此正值把该文件在时间线上向后移。注意sync_to.file必须同时出现在files列表里。manifest 的完整语法、默认值与错误目录见 trace manifest 参考。
util merge 的实现细节
从 util_subcommand.cc 可以看出util merge的内部逻辑:
- 归档成员以输入文件的basename命名,manifest 的
files[].path必须与之匹配;两个输入文件同名会直接报错; - manifest 文件在归档内统一命名为
perfetto_manifest.json,无论传入的--manifest文件名是什么; - 打包前会校验 manifest 中的每个
path都指向某个输入文件(CheckManifestPaths),防止写错名字被静默忽略; - 除非
--no-validate,打包后会以 tokenize-only 模式试运行一次(ValidateMergedArchive),统计三类会导致事件被丢弃的 stats——clock_sync_unrelatable_clock_domains、clock_sync_failure_no_path、trace_sorter_negative_timestamp_dropped——非零则警告(--strict时报错)。
验证合并结果
打开合并后的 trace,可以通过 SQL 检查合并过程中发生了什么:
-- 合并 trace 中的机器及各机器数据量。 SELECT m.name, m.raw_id, (SELECT COUNT(*) FROM thread t WHERE t.machine_id = m.id) AS threads FROM machine m; -- 输入文件及其处理顺序。 SELECT name, trace_type, size FROM trace_file; -- 合并过程中被丢弃或错位的事件;空结果意味着所有事件都放上了时间线。 SELECT name, value, machine_id, trace_id FROM stats WHERE severity = 'error' AND value > 0;与合并相关的 stats 含义:clock_sync_unrelatable_clock_domains与clock_sync_failure_no_path统计时钟无法关联到时间线的事件(对策是录制时钟快照或添加 manifestclocks条目);trace_sorter_negative_timestamp_dropped统计因offset_ns被移到时间线起点之前而丢弃的事件。每个文件的元数据可通过metadata表的trace_id列获取。
互操作注意事项
- Android bugreport:
bugreport.zip本身就是归档,Trace Processor 会直接解包并合并其中的 trace; - trace_processor bundle:
bundle子命令产出的 TAR(trace 加符号)走的是同一套归档机制; - Python
BatchTraceProcessor不做合并:它把 N 条 trace 加载进 N 个独立实例并行查询;要合并请把单个归档传给单个TraceProcessor实例; - 归档嵌套归档不能递归合并,需直接合并叶文件;
- 隐藏文件会被忽略:归档中任何路径组件以
.开头的条目都会被跳过,例如 macOS 归档工具自动生成的 AppleDouble 资源叉文件(._foo)和.DS_Store。因此 macOS 上打的.tar/.zip可以直接加载而不会报"unknown trace type"。
导出解析后的数据:export 子命令
export把解析后的 trace 数据写入文件。第一个位置参数是格式,-o FILE指定输出路径:
trace_processor export perfetto -o archive.tar trace.pftrace trace_processor export arrow_tar -o tables.tar trace.pftrace trace_processor export sqlite -o trace.db trace.pftrace三种格式的核心区别(CLI 参考):
perfetto:静态表的"版本耦合"归档。同一版本的 trace processor 新实例可以把它当 trace 重新加载;不同版本可能能加载,但不保证。它是唯一可以重新加载的格式。arrow_tar:每个静态注册表对应一个标准 Apache Arrow 文件,打包进 tar。跨 trace processor 版本稳定,适合用 pandas、Polars 或 pyarrow 分析;不能被加载回trace processor。sqlite:静态注册表加上 trace 的视图,导出为任意 SQLite 工具都能打开的数据库文件。
三种格式都导出静态注册表;只有sqlite包含视图。会话期间创建的运行时表(如CREATE PERFETTO TABLE的结果)不会被导出。从 export_subcommand.cc 的实现看,导出会流式写入磁盘,因此处理大型 trace 时内存占用保持有界。-o是必填标志。
export导出的是解析后的表格数据;如果你要导出 trace 本身(转换为其他 trace 格式),请用下一节的convert。
转换为其他 trace 格式:convert 子命令
convert封装了 traceconv 工具,把 Perfetto trace 翻译成其他格式,例如 Chrome JSON(可在chrome://tracing或其他 Catapult 工具中加载)或 pprof:
trace_processor convert json trace.pftrace trace.json trace_processor convert text trace.pftrace trace.txt支持的格式(convert_subcommand.cc 与 traceconv 快速入门):
| 格式 | 输出 |
|---|---|
text | protobuf 文本格式——protos 的文本表示 |
json | Chrome JSON 格式,可在chrome://tracing中查看 |
systrace | Android systrace 使用的 ftrace 文本/HTML 格式 |
ctrace | 压缩的 systrace 格式 |
profile | 聚合后的 pprof profile(heapprofd、perf、Java heap graphs) |
firefox | Firefox profiler 格式 |
省略输入或输出路径时分别使用 stdin 与 stdout。profile格式比较特殊:它把一个或多个.pb文件写入目录(默认是随机临时目录),因此要用--output-dir而不是位置参数:
trace_processor convert profile --output-dir ./profiles trace.perfetto-trace trace_processor convert profile --java-heap --pid 1234 --output-dir ./profiles trace.perfetto-trace trace_processor convert profile --perf --timestamps 1000000,2000000 --output-dir ./profiles trace.perfetto-trace常用选项(实现于 convert_subcommand.cc):
--truncate start|end(systrace、json、ctrace):只保留 trace 的开头或结尾;--full-sort(systrace、json、ctrace):强制完整排序;--skip-unknown(text):跳过未知 proto 字段;--alloc、--perf、--java-heap(profile):限定单一 profile 类型(默认自动检测);三者同时传时后者覆盖前者;--no-annotations(profile):不给帧添加派生注解;--pid、--timestamps(profile):按进程或采样时间戳过滤;这两个选项仅profile格式可用,其他格式会报错;--output-dir DIR(profile):pprof 文件输出目录。
运行trace_processor convert --help(或trace_processor help convert)可查看当前版本支持的完整格式列表。需要说明的是:历史上独立的traceconv工具已并入trace_processor,旧下载链接仍作为向后兼容别名工作,但新脚本与文档应统一使用trace_processor。
其他常用子命令速览
trace_processor是子命令式 CLI,全局形式为trace_processor <command> [flags] [positional args];不带子命令只传 trace 文件时,默认打开交互式 SQL shell(等价于interactive)。完整命令清单见 trace-processor-cli.md:
interactive:交互式 PerfettoSQL REPL,唯一子命令专属标志是-W, --wide;server:http(默认端口 9001,Perfetto UI 连的就是它,可用--port、--ip-address、--additional-cors-origins配置)、stdio(面向内嵌子进程的定长前缀 RPC)、unix(具名会话)与kill四种模式;summarize:计算 trace 摘要,内置 v2 指标用--metrics-v2 all或逗号分隔的指标 id 选择,spec 文件按扩展名.pb/.textproto识别二进制或文本,并支持内容嗅探兜底;bundle:把 trace 与原生符号包、Java/Kotlin 反混淆包打成自包含 TAR;符号路径按--symbol-paths、PERFETTO_BINARY_PATH与自动发现目录(/usr/lib/debug、$HOME/.debug、$ANDROID_PRODUCT_OUT/symbols、Gradle CMake 输出等)组装,详见 符号化指南;util:merge、symbolize、deobfuscate、decompress_packets、text_to_binary等底层工具;metrics:旧版 v1 指标,新工作流请用summarize --metrics-v2。
全局标志对所有子命令生效(CLI 参考):-h/--help、-v/--version、--no-progress、trace 摄取相关(--full-sort、--no-ftrace-raw、--analyze-trace-proto-content、--crop-track-events)、PerfettoSQL 包(--add-sql-package、--override-sql-package、--override-stdlib)、指标扩展(--metric-extension)、辅助文件(--register-files-dir)、开发选项(--dev、--extra-checks)以及元追踪(-m/--metatrace,用于给 trace processor 自身打 trace 做性能排查)。诊断信息输出到 stderr,只有 stderr 是终端且TERM不为dumb时才启用实时进度与 ANSI 颜色;颜色也可通过FORCE_COLOR/NO_COLOR环境变量覆盖。
下一步
- 编写查询本身:PerfettoSQL 入门;
- 用 Python 自动化批量分析多条 trace:Batch Trace Processor;
- 全部子命令与标志的权威参考:Trace Processor command-line reference;
- 命令行合并的进阶场景与验证方法:Merging traces from the command line;
- 底层 traceconv 工具与格式转换细节:Converting from Perfetto。
【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考