3、perf工具入门:perf list、perf stat、perf record、perf report基本用法

说实话,很多做性能优化的朋友,一上来就喜欢用各种花里胡哨的工具。但我个人觉得,perf 才是 Linux 性能剖析的「基本功」。它就像一把瑞士军刀,轻量、直接、而且几乎无处不在。

我记得刚入行那会儿,遇到一个 CPU 跑满的问题,同事让我用 perf 看看。我当时连 perf list 都不知道,硬着头皮查了半天文档。后来才发现,perf 其实没那么复杂,核心就四个命令:list、stat、record、report。把这四个玩明白了,80% 的性能问题你都能找到方向。

3.1 perf list:看看你的硬件支持什么

perf list 说白了就是告诉你:你的 CPU 能监控哪些事件。不同的 CPU 型号,支持的事件列表是不一样的。比如 Intel 的 CPU 有 L1 缓存命中率、分支预测失败率,ARM 的 CPU 可能就不一样。

用法很简单:

# 列出所有可用事件
perf list

# 只看硬件事件
perf list hw

# 只看软件事件
perf list sw

# 只看缓存相关事件
perf list cache

输出结果会分成几大类:

事件类别 说明 示例
硬件事件 CPU 硬件计数器 cpu-cycles, instructions, cache-misses
软件事件 内核软件事件 context-switches, page-faults, cpu-clock
tracepoint 事件 内核静态插桩点 syscalls:sys_enter_read, block:block_rq_complete
小技巧: 我习惯先用 perf list hw 看看硬件支持哪些事件。如果发现 cache-misses 不可用,那可能是虚拟机环境或者 CPU 太老,这时候就得换软件事件来分析了。

3.2 perf stat:快速看一眼性能数据

perf stat 就像体检时的「快速筛查」。你不需要深入分析,就想知道程序跑得怎么样——CPU 利用率高不高?缓存命中率行不行?上下文切换频繁不频繁?

用法:

# 统计一个命令的执行情况
perf stat ./my_program

# 统计正在运行的进程(PID 为 12345)
perf stat -p 12345

# 统计多个事件
perf stat -e cycles,instructions,cache-misses ./my_program

输出示例:

 Performance counter stats for './my_program':

       1,234,567,890      cycles                    #    3.45 GHz
       2,345,678,901      instructions              #    1.90  insn per cycle
          12,345,678      cache-misses              #    5.2% of all cache refs
               1,234      context-switches          #    0.001 /sec

       0.357892345 seconds time elapsed

这里有几个关键指标:

  • instructions per cycle (IPC):每个时钟周期执行了多少条指令。IPC 越高,说明 CPU 利用率越好。一般 IPC 低于 1 就要警惕了。
  • cache-misses 比例:缓存未命中率。超过 10% 通常意味着内存访问模式有问题。
  • context-switches:上下文切换次数。如果这个数字很大,说明你的程序在频繁争抢 CPU。
避坑指南: 我曾经遇到过一个案例,perf stat 显示 IPC 只有 0.5,但 CPU 占用率 100%。一开始以为是代码效率低,后来发现是虚拟机 CPU 超分导致的「假忙」。所以 perf stat 的数据一定要结合场景看,别盲目下结论。

3.3 perf record:把性能数据录下来

perf stat 只能看个大概,真要定位问题,得用 perf record。它会把采样数据保存下来,供后续分析。你可以把它理解成「性能录像机」。

用法:

# 默认采样 CPU 周期事件
perf record ./my_program

# 指定采样事件和频率
perf record -e cache-misses -F 99 ./my_program

# 采样正在运行的进程
perf record -p 12345 -g -- sleep 10

参数说明:

  • -e:指定要采样的事件,比如 cycles、cache-misses
  • -F:采样频率,单位 Hz。99 表示每秒采样 99 次,适合大多数场景
  • -g:记录调用栈,这个很重要!没有调用栈你根本不知道是哪个函数在消耗资源
  • -- sleep 10:采样 10 秒后自动停止
注意: 采样频率别设太高。我曾经设过 -F 9999,结果 perf 自己就把 CPU 吃满了,反而干扰了目标程序。一般 99 或 199 就够用了。

3.4 perf report:分析采样结果

录完像之后,就该看回放了。perf report 会读取 perf.data 文件,生成一个交互式的分析报告。

用法:

# 默认读取 perf.data
perf report

# 指定输入文件
perf report -i my_perf.data

# 按调用栈排序
perf report -g graph

进入交互界面后,你会看到类似这样的输出:

Samples: 1K of event 'cycles'
Event count (approx.): 1234567890

Overhead  Command  Shared Object      Symbol
  45.2%  my_prog  my_prog            [.] compute_heavy
  22.1%  my_prog  libc-2.31.so       [.] malloc
  10.5%  my_prog  my_prog            [.] parse_input
   8.3%  my_prog  [kernel]           [k] do_syscall_64
   ...

关键解读:

  • Overhead:该函数占用的 CPU 时间比例。45.2% 说明 compute_heavy 是热点函数。
  • Symbol:函数名。如果是 [.] 表示用户态,[k] 表示内核态。
  • 按 Enter 可以展开调用栈,看到是谁调用了这个函数。
我的习惯: 拿到 perf report 后,我一般先看 Overhead 最高的前三个函数。如果它们加起来超过 60%,那问题基本就锁定了。然后按 Enter 看调用链,找到「罪魁祸首」的调用路径。

3.5 一张图看懂 perf 工作流程

下面这张 SVG 图,把 perf 的核心流程串起来了。你一看就明白:

perf 工具核心工作流程 perf list 查看可用事件 perf stat 快速统计概览 perf record 采样录制数据 perf.data 采样结果文件 perf report 分析热点函数 快速筛查 如果 stat 数据异常 再进入 record 阶段

这张图很直观:先用 perf list 看看武器库,然后用 perf stat 快速扫描,发现问题后再用 perf record 深入采样,最后 perf report 给出分析结果。说白了,就是「先粗后细、层层深入」的思路。

3.6 实战小例子:定位 CPU 热点

光说不练假把式。咱们拿一个实际场景走一遍:

# 1. 先看看程序跑得怎么样
perf stat ./my_app

# 输出显示 IPC 只有 0.8,cache-misses 高达 15%
# 嗯,有问题

# 2. 深入采样,记录调用栈
perf record -e cache-misses -F 99 -g ./my_app

# 3. 分析结果
perf report -g graph

在 perf report 界面里,我发现 hash_lookup 函数占了 40% 的 cache-misses。点进去一看,调用链是 process_request -> hash_lookup。原来是一个哈希表查询频繁 miss。

后来我改成了更紧凑的数据结构,cache-misses 降到了 5%,性能提升了 3 倍。你看,perf 就是这么用的。

核心总结: perf list 看武器,perf stat 做体检,perf record 录视频,perf report 看回放。这四个命令串起来,就是一套完整的性能分析流水线。

想要更多资料,联系可可