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

目录

Trace Processor
使用方式
CLI版本:traceprocessorshell
Python API
Perfetto UI 内置
核心概念
时间单位
唯一标识符
表基本信息
表结构
常用查询模式
查找最耗时的事件
统计特定事件的耗时分布
搜索特定名称的 Slice
分析线程状态分布
CPU 利用率分析
提取 ftrace 事件参数
10. 内存计数器趋势
SQLite 的窗口函数
总结
参考资料

根据之前的文章,我们详细的了解了perfetto的基本使用技巧,这篇文章我们聚焦在perfetto的sql语句,说明其工作原理和如何进行sql查找

Trace Processor

Trace Processor 是 Perfetto 生态中最强大的组件之一,它将复杂的二进制 trace 数据转化为可查询的关系型数据库结构,让你可以用 SQL 的方式精确分析性能数据。

Trace Processor 是一个 C++ 库,核心能力包括:

  • 多格式解析:解析 Perfetto protobuf、Systrace 文本、Chrome JSON、perf.data 等多种 trace 格式
  • 统一 SQL 接口:将所有数据暴露为一组一致的 SQL 表
  • 低延迟查询:为构建可视化工具优化的查询性能
  • 跨平台:在 Perfetto UI 中作为 WebAssembly 模块运行,也可作为独立工具或 C++ 库使用

使用方式

perfetto提供了三种使用sql的办法。分别如下

CLI版本:trace_processor_shell

通过下载perfetto的binary可以获取 trace_processor_shell

bash
# wget https://github.com/google/perfetto/releases/download/v54.0/linux-amd64.zip

我们可以直接将sql作为参数输入给 trace_processor_shell

# ./trace_processor_shell --help [290.273] processor_shell.cc:1016 Interactive trace processor shell. Usage: ./trace_processor_shell [FLAGS] trace_file.pb PerfettoSQL: -q, --query-file FILE Read and execute an SQL query from a file. If used with --run-metrics, the query is executed after the selected metrics and the metrics output is suppressed. -Q, --query-string QUERY Execute the SQL query QUERY. If used with --run-metrics, the query is executed after the selected metrics and the metrics output is suppressed. --add-sql-package PATH[@PACKAGE] Registers SQL files from a directory as a package for use with INCLUDE PERFETTO MODULE statements. By default, the directory name becomes the root package name. Use @PACKAGE to override. Given a directory structure: mydir/ utils.sql helpers/common.sql --add-sql-package ./mydir Registers modules as: mydir.utils mydir.helpers.common Usage: INCLUDE PERFETTO MODULE mydir.utils; --add-sql-package ./mydir@foo Registers modules as: foo.utils foo.helpers.common Usage: INCLUDE PERFETTO MODULE foo.utils; --add-sql-package ./mydir@foo.bar.baz Registers modules as: foo.bar.baz.utils foo.bar.baz.helpers.common Usage: INCLUDE PERFETTO MODULE foo.bar.*;

Python API

同样,我们可以直接使用perfetto的python包,也能够进行sql查询,只需要按照perfetto即可

pip3 install perfetto

安装完成后,pip list可以查看如下

perfetto 0.14.0

此时代码可以直接加载sql进行查询

python
from perfetto.trace_processor import TraceProcessor tp = TraceProcessor(trace='trace.perfetto-trace') qr_it = tp.query('SELECT ts, dur, name FROM slice LIMIT 10') for row in qr_it: print(row.ts, row.dur, row.name)

Perfetto UI 内置

在 Perfetto UI 底部的 "Query (SQL)" 标签中直接输入和执行 SQL 查询。点击即可

image.png

核心概念

时间单位

Perfetto 中所有时间值以纳秒(ns) 为单位:

  • ts(timestamp):事件开始时间,纳秒
  • dur(duration):事件持续时间,纳秒
  • 转换:dur / 1e6 = 毫秒,dur / 1e9 = 秒

唯一标识符

Perfetto 使用内部唯一标识符,而非系统的 PID/TID:

  • utid(Unique TID):线程的唯一标识
  • upid(Unique PID):进程的唯一标识
  • 同一个 PID 在 trace 中被回收重用时,utid/upid 仍然唯一

表基本信息

  • slice:一个时间片
  • counter:一个计数器
  • thread:线程状态

表结构

slice存储所有有时长的事件(函数调用、ATrace 标记等),其结构如下

sql
SELECT id, ts, -- 开始时间(纳秒) dur, -- 持续时间(纳秒) name, -- 事件名称 category, -- 事件类别 track_id, -- 所属轨道 depth, -- 嵌套深度 parent_id, -- 父事件 ID arg_set_id -- 参数集 ID FROM slice;

thread 和 process 表提供了关于线程的id信息

sql
-- 线程信息 SELECT utid, tid, name AS thread_name, upid FROM thread; -- 进程信息 SELECT upid, pid, name AS process_name FROM process;

thread_state 表提供了线程的状态信息

sql
SELECT ts, dur, utid, state, -- 'Running', 'R' (Runnable), 'S' (Sleeping), -- 'D' (Uninterruptible Sleep), 'T' (Stopped) cpu, -- 运行在哪个 CPU blocked_function -- D 状态时阻塞在哪个内核函数 FROM thread_state;

counter 表 默认记录了CPU 频率、内存等随时间变化的数值

sql
SELECT ts, value, track_id FROM counter;

sched_slice 表提供了调度事件,记录每个 CPU 上的调度切换:

sql
SELECT ts, dur, cpu, utid, end_state, -- 线程被切出时的状态 priority FROM sched_slice;

ftrace_event 表:原始 ftrace 事件

sql
SELECT ts, name, cpu, utid, arg_set_id FROM ftrace_event;

常用查询模式

现在以android上的完整示例进行sql演示

查找最耗时的事件

sql
SELECT s.name, s.dur / 1e6 AS dur_ms, t.name AS thread_name, p.name AS process_name FROM slice s JOIN thread_track tt ON s.track_id = tt.id JOIN thread t ON tt.utid = t.utid JOIN process p ON t.upid = p.upid ORDER BY s.dur DESC LIMIT 20;

image.png

可以看到用时最多的是,PortraitProc的PortraitProcessor::Process

统计特定事件的耗时分布

sql
SELECT name, COUNT(*) AS count, MIN(dur) / 1e6 AS min_ms, MAX(dur) / 1e6 AS max_ms, AVG(dur) / 1e6 AS avg_ms, SUM(dur) / 1e6 AS total_ms FROM slice WHERE name GLOB '*Trace GPU completion fence*' GROUP BY name ORDER BY total_ms DESC;

image.png

可以看到fence 864 耗时0.71224ms,最长

搜索特定名称的 Slice

sql
-- 使用 GLOB 进行模糊搜索 SELECT ts, dur / 1e6 AS dur_ms, name FROM slice WHERE name GLOB '*GPU*' LIMIT 20; -- 使用 LIKE 搜索 SELECT ts, dur / 1e6 AS dur_ms, name FROM slice WHERE name LIKE '%GPU%' ORDER BY dur DESC LIMIT 10;

image.png

这个sql经常使用,直接找slice,然后导出track如下

image.png

分析线程状态分布

sql
SELECT state, SUM(dur) / 1e6 AS total_ms, COUNT(*) AS count FROM thread_state GROUP BY state

image.png

CPU 利用率分析

sql
-- 每个 CPU 的利用率 SELECT cpu, SUM(dur) / 1e6 AS busy_ms, (SELECT MAX(ts) + MAX(dur) - MIN(ts) FROM sched_slice) / 1e6 AS total_ms, CAST(SUM(dur) AS FLOAT) / (SELECT MAX(ts) + MAX(dur) - MIN(ts) FROM sched_slice) * 100 AS util_pct FROM sched_slice GROUP BY cpu ORDER BY cpu;

image.png

提取 ftrace 事件参数

sql
SELECT EXTRACT_ARG(arg_set_id, 'prev_comm') AS prev_comm, EXTRACT_ARG(arg_set_id, 'prev_pid') AS prev_pid, EXTRACT_ARG(arg_set_id, 'next_comm') AS next_comm, EXTRACT_ARG(arg_set_id, 'next_pid') AS next_pid FROM ftrace_event WHERE name = 'sched_switch' LIMIT 20;

image.png

10. 内存计数器趋势

sql
SELECT c.ts / 1e9 AS ts_sec, c.value / 1024 AS value_kb, ct.name AS counter_name FROM counter c JOIN counter_track ct ON c.track_id = ct.id WHERE ct.name LIKE '%mem%' ORDER BY c.ts;

image.png

SQLite 的窗口函数

PerfettoSQL 支持 SQLite 的窗口函数,适合计算滑动平均等:

sql
SELECT ts / 1e9 AS ts_sec, value, AVG(value) OVER ( ORDER BY ts ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING ) AS moving_avg FROM counter WHERE track_id = 50;

image.png

总结

Trace Processor 和 PerfettoSQL 是 Perfetto 分析能力的核心。熟练掌握这些sql,能够让你性能分析事半功倍

同样的,如果借助ai给你这些sql,相比于原来手搓sql更加轻松

参考资料