第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_ms5000~30000太长则文件过大;缓存热点通常可见于数十秒周期
buffers.size_kb≥ 32768(32 MB)避免环形缓冲覆盖关键事件
ftrace_eventsmm_event/*, sched/sched_switch, task/task_newtask必须包含缓存缺失与页面缓存操作事件
linux.perf counterL1-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主要由以下区域组成:

  1. 导航栏(顶部):时间轴缩放、选择trace文件、配置面板。
  2. 全局时间轴(Gantt图主区):显示所有进程/线程的活动与状态,默认按cpu、进程分组。
  3. 左侧Track列表:列举每个进程及其子线程,可折叠/展开,包含ftrace、sched、mem等track。
  4. 详情侧面板(右键点击事件后出现):显示事件的具体字段(如缓存缺失地址、pid、latency等)。
  5. 查询栏:支持SQL(PerfettoSQL)与过滤表达式,用于精确筛选缓存事件。
  6. 统计概览:快速汇总各进程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抓取质量

修复配置后,重新抓取并确认以下三条:

  1. UI中“Events”总数不得少于5000(否则可能是配置错误导致事件缺失)。
  2. 过滤cache后,至少出现两个以上不同track。
  3. 时间轴无大段空白(超过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
└─ 配置中缺少mm_event category → 添加ftrace_events
└─ kernel版本不支持mm_event → 换用linux.perf counter
└─ buffer太小导致事件丢失 → 增加size_kb至64M
└─ trace文件权限不足 → 使用chmod 777或root执行
Perfetto Trace抓取与基础分析流程(缓存瓶颈方向) 1 现象识别 高缓存缺失/卡顿 2 配置选择 mm_event + perf counter 3 执行抓取 perfetto 命令 / adb shell 4 生成文件 cache_trace.pftrace 5 导入UI ui.perfetto.dev 6 定位Track cpu_cache / mm_cache 7 分析事件 缺失地址 / 阻塞原因 8 确认缓存瓶颈 复测通过 / 进入调优 说明 步骤1-4属于“数据采集” 步骤5-7属于“原因定位”
SVG流程解读:图中红色节点(1、7)对应“现象识别”与“原因定位”;蓝色节点(2、8)为配置与结论;绿色为抓取执行;紫色为产物;橙色为UI导入;青色为track定位。整体按排查主线从左至右再折返。