☰ 第 13 章 · perf:Linux 官方剖析器
COURSE SOURCES

参考来源与版权说明

仅作来源说明 · 不提供原始资料下载
查看全部来源说明
01
START HERE

这章解决什么问题

perf 是 Linux perf_events 子系统的官方前端。它把硬件性能计数器、内核软件事件、tracepoint、kprobe、uprobe 和 USDT 放进相近的命令模型,用来回答:CPU 时间花在哪些函数、每周期完成多少指令、线程为何频繁切换、哪条代码路径发起了 I/O。

真正需要掌握的不是几十个子命令,而是一条渐进路径:先用 stat 数事件并估计频率,再用 record 采样到 perf.data,之后用 report 做聚合、用 script 看时间顺序或供火焰图处理。

02
SECTION 02

五条核心结论

  1. 事件源决定答案。 cycles/instructions 描述微架构,软件事件描述内核计数,tracepoint 与探针描述具体行为。
  2. perf stat 负责“多少”,perf record 负责“在哪里/何时”。 先计数通常更便宜,也能估算后续跟踪开销。
  3. 采样不是逐事件记录。 高频 PMC 和软件事件常按频率抽样;tracepoint 通常可按周期 1 记录全部事件,但事件太频繁时仍有开销。
  4. 栈和符号质量决定剖析价值。 帧指针、DWARF/LBR、调试符号和内核符号缺失,都会造成断栈或 unknown。
  5. 结果依赖处理器、内核与权限。 同名硬件事件的映射、精确采样能力、可用 tracepoint 和 perf 安全策略都可能不同。
03
SECTION 03

核心模型与关键指标

可以把 perf 看成四层:

~~~text

事件源 → 收集方式 → 数据文件/实时流 → 汇总与可视化

PMC stat计数 文本计数 IPC、缓存命中、频率

软件事件 record采样 perf.data 热点、栈、火焰图

tracepoint perf.data 时间线、参数、延时

动态探针 trace实时 标准输出 临时验证

~~~

CPU 分析常看 cycles、instructions 和 IPC(instructions / cycles),再结合 cache-misses、branch-misses。调度问题常看 context-switches 和 sched 事件。数据质量还要看样本数、采样频率、是否丢事件、记录时长、CPU/PID/cgroup 范围以及符号解析比例。

<code>-F 99</code> 表示目标采样频率约为每秒 99 次,而 <code>-c 1</code> 表示每发生一次事件就触发记录;二者语义不同。内核会限制采样率和 perf 可占 CPU 比例,超载时可能节流。

事件的作用域也是测量模型的一部分。<code>-a</code> 代表全系统,<code>-p</code> 与 <code>-t</code> 分别限定进程和线程,<code>-G</code> 可面向 cgroup。全系统结果适合发现“谁在消耗”,进程结果适合验证某服务,但线程迁移、子进程以及容器边界都可能让范围漏数。硬件事件还可区分用户态和内核态。报告时应写清作用域,否则同一计数无法复现。

04
SECTION 04

诊断步骤

  1. 用 <code>perf --version</code>、<code>perf list</code> 和只读 sysctl 值确认工具、事件与权限。
  2. 先跑 <code>perf stat</code>:确认目标事件确实发生,估算频率,并检查 IPC、切换率等大方向。
  3. 缩小范围:优先指定 PID、命令、cgroup 或短时全系统窗口,避免无边界收集。
  4. 对 CPU 热点用 49/99 Hz 采样并记录栈;对离散行为选稳定 tracepoint。
  5. 用 report 看聚合热点,用 script 看时间顺序、字段和元数据;必要时再生成火焰图。
  6. 核查符号、断栈和 lost 计数,并与 vmstat、pidstat、应用指标交叉验证。
05
SECTION 05

常用工具与命令

以下命令默认不改变业务配置;record 会在当前目录生成 perf.data。很多系统需要 root、CAP_PERFMON 或放宽策略,命令选项也可能随版本改变。

~~~bash

# 列出本机实际支持的事件

perf list

sysctl kernel.perf_event_paranoid

# 统计全系统周期、指令与上下文切换,持续 10 秒

perf stat -e cycles,instructions,context-switches -a -- sleep 10

# 每秒输出一次 sched 切换计数

perf stat -e sched:sched_switch -a -I 1000

# 全系统 CPU 栈采样,99 Hz,30 秒

perf record -F 99 -a -g -- sleep 30

perf report --stdio -n

# 记录块请求 10 秒,再按时间顺序输出

perf record -e block:block_rq_issue -a -- sleep 10

perf script

# 保留头信息与稳定字段,便于后处理

perf script --header -F comm,pid,tid,cpu,time,event,ip,sym,dso,trace

~~~

若默认帧指针回溯损坏,可在测试环境尝试 <code>--call-graph dwarf</code>;它通常需要调试信息且数据量更大。事件过滤字段先查看对应 tracefs format 文件,切勿照搬另一内核的字段名。

06
SECTION 06

如何解读结果

stat 中 cycles 与 instructions 可推导 IPC,但低 IPC 不是单一结论:它可能来自缓存/内存停滞、分支、超线程竞争或工作负载本身。先与同架构、同负载基线比较。事件计数若显示“not supported”或异常为零,应先怀疑事件映射和权限。

report 的 Overhead 是样本占比,不等于精确墙钟时间;热点函数要结合调用栈理解是谁触发。script 每行包含进程/线程、CPU、时间、事件与参数,适合发现阶段性行为;header 能保存主机、内核、CPU 和原始命令,是日后复盘的重要证据。

调度类问题可先比较上下文切换总率和每 CPU 分布,再记录 sched_switch/sched_wakeup 事件回答“谁睡眠、谁唤醒、在哪个 CPU”。块 I/O 也应先计数和看设备队列,再记录 issue/complete 时间线。这样可避免把一个高频但与用户延时无关的事件误当根因。

采样频率越高时间分辨率越好,但开销和数据量也增加。99 Hz 常用于避开与整百周期性任务的同步,同时保持较低成本;它不是所有场景的固定答案。

还要区分进程 ID、线程 ID 与命令名。多线程服务的热点可能只落在少数工作线程,短命线程也可能在汇总前退出。需要解释不均衡时,应保留 tid 与 CPU 字段,并把 perf 时间线和应用线程池、请求日志对齐,不能只按相同的进程名合并。

07
SECTION 07

常见误判

  • 把样本数量当作事件总数,忽略频率采样和周期采样的区别。
  • 看见某函数样本多就直接修改它,未检查调用者和工作负载。
  • 不保存 perf 版本、内核、命令和头信息,导致 perf.data 无法解释或迁移。
  • 忽略 lost/节流、unknown 符号和断栈,仍把图当成完整事实。
  • 在不同处理器上直接比较裸 PMC,或默认相信人类可读事件映射完全正确。
  • 记录所有 CPU、所有高频事件且没有时限,使观测本身干扰系统。
08
SECTION 08

五分钟自测

  1. 想知道“事件发生多少次”,优先用哪个子命令?
  2. <code>-F 99</code> 与 <code>-c 1</code> 的核心区别是什么?
  3. report 和 script 分别擅长哪类问题?
  4. CPU 栈出现大量 unknown 时先检查什么?
  5. 为什么先用 stat 估计 tracepoint 频率?

检查要点:stat;频率采样与逐事件周期;聚合热点与时间序列;符号/调试信息/栈遍历;判断 record 全量捕获的开销和数据规模。

09
SECTION 09

本章小结

perf 的最小有效闭环是“list 确认事件 → stat 低成本计数 → record 短时采样 → report/script 解读 → 与其他指标验证”。每次都写明事件、范围、时长、采样语义和数据质量,才能把漂亮的火焰图变成可靠证据。

10
SECTION 10

来源定位

主题PDF 页码
功能、子命令与事件概览717-727
硬件/软件事件与采样语义727-730
tracepoint、kprobe、uprobe、USDT730-737
stat、record 与栈遍历737-743
report、script、火焰图与 trace743-749
其他命令与文档749-751
📝
QUICK CHECK

章节测验

5 道单选题。答错有解析,答对看来源页码。

单选题 · 第 1/5
已答 0/5

想先知道某 tracepoint 在 10 秒内发生了多少次,通常应优先使用哪个 perf 子命令?

⚡ 用本章题目开始计时冲刺