perf 是 Linux 内核自带的一款性能分析工具,集成在内核源码树的 tools/perf 目录中。它直接利用内核的 perf_events 子系统,通过采样和计数硬件、软件事件,帮助你精准定位 CPU 层面的性能瓶颈——哪些函数消耗了最多的 CPU 周期,哪里发生了过多的缓存失效,哪条分支预测频繁出错等。由于数据直接来源于内核和硬件性能监控单元(PMU),perf 的开销极低,适合在线上生产环境谨慎使用。
核心概念
- 事件:
perf能采集多种事件,包括硬件事件(CPU 周期、指令数、缓存命中/失效、分支预测失误)、软件事件(上下文切换、页面错误)和内核调用栈等。 - 采样:以固定频率或基于事件计数采集当前的指令指针(IP)和调用栈。通过统计样本分布,可以推断出程序大部分时间停在哪里(热点)。
- 计数:直接统计某个事件在指定时间段内的总次数,例如
perf stat展示程序运行期间共消耗了多少 CPU 周期和指令。
常用子命令与典型用法
perf top:实时交互式热点分析
sudo perf top
它会实时刷新,展示当前系统中消耗 CPU 周期最多的函数(默认按 CPU 周期排序)。按下 s 键可切换到只看某个进程。这是快速检查系统 CPU 是否被异常进程或内核函数占用的第一手段。
perf stat:事件计数,概览性能指标
perf stat -d ls /
运行 ls / 并输出详细的事件计数:时钟周期、指令数、分支数、分支预测缺失、各级缓存访问/失效等。可以快速评估一个命令的计算密度和缓存友好程度。如果 CPI(环指令数/周期)远高于预期,说明程序可能受缓存或内存延迟影响。
perf record+perf report:对特定进程或命令进行采样并生成报告
sudo perf record -g -p 1234 -- sleep 30 # 对 PID 1234 采样 30 秒,记录调用栈
sudo perf report -g graph # 生成带调用图的交互式火焰图
这是定位性能问题的核心流程。-g 选项会记录完整的调用栈,后续 perf report 可以直观看到每个函数的 CPU 占比以及调用关系(相当于简易火焰图)。如果想生成真正的火焰图,可以将 perf.data 导出为文本并用 Brendan Gregg 的 FlameGraph 工具渲染:
sudo perf script > out.perf
./stackcollapse-perf.pl out.perf > out.folded
./flamegraph.pl out.folded > flame.svg
perf stat分析内存与缓存行为
单靠 CPU 利用率不能说明性能瓶颈。使用 perf stat -e cache-misses,cache-references 可以观察缓存缺失率。例如:
perf stat -e cycles,instructions,cache-misses,cache-references -p 1234 -- sleep 10
通过比较指令数与周期数,判断程序是否受限于缓存(高 CPI 与高缓存缺失相关)。
perf list:列出当前系统支持的所有事件
perf list
事件根据类型分类展示,硬件事件、软件事件、内核探测器(probe)等一目了然,便于选择精确的分析维度。
实用技巧与注意事项
- 权限:一些硬件事件和进程调用栈采样需要 root 权限(
sudo),或者设置perf_event_paranoid降低限制(sudo sysctl kernel.perf_event_paranoid=-1)。 - 采样频率:
perf record默认频率可能较高(如 4000 Hz),可在命令后加-F 99控制。过高会引入额外开销并导致采样失真,但过低的频率可能遗漏短暂高峰。 - 符号解析:对于没有调试符号的程序或内核模块,
perf report可能只显示地址。可安装对应-dbgsym或-debuginfo包,或使用--symfs指定符号目录。 - 组合使用:
perf与pidstat、vmstat等工具互补。先用perf top/stat宏观确认 CPU 问题,再用perf record深入逐函数分析。
perf 是 Linux 原生、零额外依赖的强大性能分析器,对开发者和运维人员而言,熟练掌握它意味着可以在任何一台 Linux 机器上就地诊断 CPU 性能瓶颈,无需预装复杂的监控软件,是服务器性能调优与故障排查的基本功。