第2章 Perfetto Trace基础操作:抓取trace的常用命令、配置选择、trace文件结构、UI界面布局
适用场景:首次使用Perfetto排查缓存瓶颈的开发者。本章按“现象识别→数据采集→原因定位→修复动作→复测→预防”主线,建立从问题怀疑到trace获取与初步解读的完整操作基础。
2.1 现象识别 – 何时需要抓取Trace
缓存瓶颈在运行时通常表现为以下特征之一,此时应考虑抓取Perfetto trace进行定量分析:
- CPU缓存缺失率持续偏高(≥20% L1 miss / L2 miss),性能计数器警示。
- 内存访问延迟波动大,关键线程频繁卡顿在
memory_cache或page_fault区间。 - 负载测试中,吞吐量未达预期且
cache-misses硬件事件触发频率异常。 - 调度器频繁切换等待内存的线程(
sched_blocked_reason中常见mm_sync或page_fault)。
使用下表中的快速判断规则决定是否触发trace采集:
| 观察指标 | 阈值(典型) | 动作 |
|---|---|---|
| perf stat L1d-miss-rate | > 15% | 抓取包含cache category的trace |
| mpstat 连续3次 %cachemiss | > 8% | 触发perfetto --all-categories(谨慎开销) |
| ftrace buffer 中mmap_pgover | 每秒 > 500 | 立即抓取内存缓存trace |
| 用户态log提示“cache thrashing” | — | 按上一步配置进行定点抓取 |
2.2 数据采集 – 抓取Trace的常用命令与配置选择
Perfetto提供两种抓取方式:adb shell 命令行(用于Android)和系统级perfetto服务(Linux/ChromeOS)。缓存瓶颈分析需要开启内存、调度、CPU counter三类数据源。
2.2.1 常用抓取命令
以下命令适用Android设备(已root或具有perfetto权限):
# 基础缓存trace(CPU counter + sched + 内存,30秒)
adb shell perfetto -c - --txt … <<-END
duration_ms: 30000
buffers: { size_kb: 65536 fill_policy: RING_BUFFER }
data_sources: [
{ config { name: "linux.perf" } },
{ config { name: "linux.ftrace" ftrace_config { ftrace_events: ["sched/sched_switch", "mm_event/mm_cache_event"] } } },
{ config { name: "linux.process_stats" process_stats_config { scan_all_processes: true } } }
]
END
# 使用内置profile:缓存性能(Android O+)
adb shell perfetto --txt -c /dev/null -o /data/misc/perfetto-traces/cache_trace.pftrace
# 最简单的“全量”抓取(高开销,仅用于排查罕见缓存问题)
adb shell perfetto --all-categories -o /data/misc/perfetto-traces/full_trace.pftrace
2.2.2 配置选择要点
| 配置项 | 缓存瓶颈推荐值 | 说明 |
|---|---|---|
duration_ms | 5000~30000 | 太长则文件过大;缓存热点通常可见于数十秒周期 |
buffers.size_kb | ≥ 32768(32 MB) | 避免环形缓冲覆盖关键事件 |
ftrace_events | mm_event/*, sched/sched_switch, task/task_newtask | 必须包含缓存缺失与页面缓存操作事件 |
linux.perf counter | L1-dcache-load-misses, LLC-load-misses | 若内核支持,开启以获取精确缺失率 |
process_stats_config | 不扫描,仅需监控目标进程PID | 降低overhead |
配置即排查第一关:如果trace文件中缺少缓存事件,则“数据采集”环节失败。建议先使用
perfetto --query检查可用数据源,确认linux.perf和mm_event为支持状态。
2.3 原因定位 – Trace文件结构与UI界面布局
抓取成功后,得到一个.pftrace或.perfetto-trace文件。理解其结构是高效分析的前提。
2.3.1 Trace文件结构概览
Perfetto trace是protobuf序列化的包(Packet)流。主要包类型:
- TracePacket:承载实际事件(sched、mem、perf counter等)。
- TraceConfig(仅写入头部):记录抓取参数,便于事后回溯。
- InternedData:字符串表,减少重复字符串体积(事件名、进程名等)。
- Sequence:按时间排序的多段event流。
解包工具可使用perfetto/tools/traceconv或直接拖入UI。文件头部约几百KB,无需手动解析,但需知道:
| 结构区块 | 作用 | 分析关注度 |
|---|---|---|
| TraceConfig 块 | 抓取参数,确认是否包含缓存事件 | ★☆☆ |
| Process & Thread 描述 | 列出pid/tid/comm | ★★☆ |
| Ftrace Event 包 | 所有调度与缓存事件 | ★★★★ |
| Perf Counter 包 | 硬件计数器瞬时值 | ★★★★ |
| InternedData 表 | 字符串索引,通常被UI自动反解 | ★☆☆ |
2.3.2 UI界面布局(https://ui.perfetto.dev)
打开trace文件后,浏览器渲染的UI主要由以下区域组成:
- 导航栏(顶部):时间轴缩放、选择trace文件、配置面板。
- 全局时间轴(Gantt图主区):显示所有进程/线程的活动与状态,默认按cpu、进程分组。
- 左侧Track列表:列举每个进程及其子线程,可折叠/展开,包含
ftrace、sched、mem等track。 - 详情侧面板(右键点击事件后出现):显示事件的具体字段(如缓存缺失地址、pid、latency等)。
- 查询栏:支持SQL(PerfettoSQL)与过滤表达式,用于精确筛选缓存事件。
- 统计概览:快速汇总各进程cpu占用、内存分配次数、调度延迟等。
2.3.3 快速定位缓存瓶颈track
在UI中键入cache过滤track列表,重点关注:
- cpu_cache / mm_cache track:直接显示缓存事件时间线。
- sched_switch 结合 blocked_reason = mm_sync:表明线程因等待页面缓存而阻塞。
- perf counter 的
LLC-load-misses曲线:突增点即为缓存瓶颈时刻。
常见误判:UI中
memory track显示的是整体物理内存,不是缓存。必须开启mm_event和linux.perf才可看到细粒度缓存缺失事件。
2.4 修复动作 – 基于基础操作的快速验证
本章作为基础操作,不涉及具体代码调优。但提供两个检查点:
- 检查抓取配置是否命中缓存事件:在UI的“Info”窗格查看
trace_config,确认ftrace_events列表包含mm_event/mm_cache_event。 - 增加perf counter数量:如果发现
LLC-load-misses全为0,检查内核是否支持硬件PMC,或改用perf_event_open配置。
2.5 复测 – 验证Trace抓取质量
修复配置后,重新抓取并确认以下三条:
- UI中“Events”总数不得少于5000(否则可能是配置错误导致事件缺失)。
- 过滤
cache后,至少出现两个以上不同track。 - 时间轴无大段空白(超过5秒无任何事件)——表示缓冲溢出现象,需增大
buffers.size_kb。
使用perfetto --summary快速查看文件元信息:
adb shell perfetto --summary /data/misc/perfetto-traces/cache_trace.pftrace
# 输出应包含: trace_type: "PERFETTO_TRACE", num_packets: 12345, has_ftrace: yes, has_perf_counters: yes
2.6 预防 – 缓存Trace采集最佳实践
- 预定义profile:在项目仓库中保留一份
cache_profile.cfg,避免每次重复输入配置。 - 保留原始终端buffer:抓取时尽量使用
fill_policy: RING_BUFFER而非DISCARD,否则负载峰值时事件会丢失。 - 控制trace持续时间:通常30秒足够捕获90%的缓存热点,过长会导致UI加载缓慢。
- 版本匹配:perfetto UI版本会随protobuf schema更新而变,尽量使用与老trace兼容的旧UI(
https://ui.perfetto.dev/v45.0等)。
故障树 – 抓取阶段常见问题
根节点:无法获取有效缓存trace
└─ 配置中缺少
└─ kernel版本不支持mm_event → 换用
└─ buffer太小导致事件丢失 → 增加size_kb至64M
└─ trace文件权限不足 → 使用
根节点:无法获取有效缓存trace
└─ 配置中缺少
mm_event category → 添加ftrace_events└─ kernel版本不支持mm_event → 换用
linux.perf counter└─ buffer太小导致事件丢失 → 增加size_kb至64M
└─ trace文件权限不足 → 使用
chmod 777或root执行
SVG流程解读:图中红色节点(1、7)对应“现象识别”与“原因定位”;蓝色节点(2、8)为配置与结论;绿色为抓取执行;紫色为产物;橙色为UI导入;青色为track定位。整体按排查主线从左至右再折返。