4. perf 工具基础:perf list、perf stat、perf record、perf report 的基本用法与输出解读
perf 是 Linux 内核自带的性能剖析工具集,基于内核的 Performance Events 子系统,能够以极低的开销采集 CPU 周期、缓存未命中、分支预测错误、上下文切换等硬件与软件事件。掌握 perf 的四个核心子命令——perf list、perf stat、perf record、perf report——是生成火焰图与定位内核性能瓶颈的前提。
适用环境:内核版本 ≥ 2.6.31,且编译时开启了
CONFIG_PERF_EVENTS。大多数主流发行版(Ubuntu、CentOS、Debian)默认包含 perf 工具,可通过 apt install linux-tools-common 或 yum install perf 安装。
4.1 perf list:列出可观测的性能事件
perf list 用于查询当前系统支持的所有性能事件,包括硬件事件、软件事件、tracepoint 事件和动态 PMU 事件。这是 perf 使用的起点,帮助用户选择正确的观测目标。
基本用法
# 列出所有事件
perf list
# 按类别过滤(硬件、软件、tracepoint、pmu)
perf list hw
perf list sw
perf list tracepoint
perf list pmu
# 使用通配符搜索特定事件
perf list 'cache*'
perf list 'sched:*'
输出解读
输出按事件类型分组,每行包含事件名称、事件描述和默认单位。以下为典型输出片段:
List of pre-defined events (to be used in -e):
cpu-cycles OR cycles [Hardware event]
instructions [Hardware event]
cache-references [Hardware event]
cache-misses [Hardware event]
branch-instructions OR branches [Hardware event]
branch-misses [Hardware event]
cpu-clock [Software event]
task-clock [Software event]
context-switches OR cs [Software event]
page-faults OR faults [Software event]
minor-faults [Software event]
major-faults [Software event]
sched:sched_switch [Tracepoint event]
sched:sched_wakeup [Tracepoint event]
block:block_rq_complete [Tracepoint event]
syscalls:sys_enter_read [Tracepoint event]
关键点:硬件事件依赖 CPU PMU(Performance Monitoring Unit),不同架构(x86、ARM、RISC-V)支持的事件集不同。在虚拟化环境中,部分硬件事件可能不可用。
4.2 perf stat:快速统计性能计数器
perf stat 用于运行一个命令并统计其执行期间的性能计数器总和,适合快速评估程序或内核代码段的整体性能特征。
基本用法
# 统计默认事件集(cycles、instructions、cache-misses 等)
perf stat ./my_program
# 指定自定义事件
perf stat -e cycles,instructions,cache-misses,context-switches ./my_program
# 统计整个系统(所有 CPU)的计数器
perf stat -a sleep 5
# 按进程/线程统计
perf stat -p 1234 sleep 3
输出解读
典型输出包含事件名称、计数、单位、时间戳和比例关系:
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 cache-misses # 3.21% of all cache refs
5,678 context-switches # 0.001 M/sec
1,234 page-faults # 0.000 M/sec
0.357894321 seconds time elapsed
| 字段 | 含义 | 典型关注点 |
|---|---|---|
| cycles | CPU 时钟周期总数 | 高值表示 CPU 繁忙 |
| instructions | 执行的指令数 | IPC(每周期指令数)< 1 表示流水线停顿严重 |
| cache-misses | 缓存未命中次数 | 比例 > 10% 时内存访问成为瓶颈 |
| context-switches | 上下文切换次数 | 高值暗示锁竞争或 I/O 等待 |
| page-faults | 缺页异常次数 | major-faults 高表示内存不足或文件映射频繁 |
注意:
perf stat 给出的是聚合值,无法展示事件随时间的变化。若需定位热点函数或代码路径,必须使用 perf record 进行采样。
4.3 perf record:采样并记录性能数据
perf record 以指定频率对 CPU 进行采样,记录每个采样点正在执行的函数(或内核栈),生成 perf.data 文件。这是生成火焰图的数据来源。
基本用法
# 以 99 Hz 采样目标程序(避免与系统 tick 同步)
perf record -F 99 ./my_program
# 采样整个系统(所有 CPU、所有进程)
perf record -a -F 99 sleep 10
# 采样特定进程
perf record -p 1234 -F 99 sleep 10
# 记录调用栈(生成火焰图必需)
perf record -F 99 --call-graph dwarf ./my_program
# 指定输出文件
perf record -o my_perf.data -F 99 ./my_program
采样频率选择
| 场景 | 推荐频率 | 说明 |
|---|---|---|
| CPU 密集型程序 | 99 Hz | 避免与内核调度 tick(通常 100 Hz)共振 |
| I/O 密集型或短生命周期程序 | 1000–4000 Hz | 提高采样密度以捕获短时事件 |
| 全系统长时间监控 | 49–99 Hz | 降低采样开销,避免影响系统行为 |
调用栈采集方式:
--call-graph dwarf 使用 DWARF 调试信息展开栈,兼容性好但开销较大;--call-graph fp 使用帧指针(frame pointer),开销小但要求程序编译时加 -fno-omit-frame-pointer。火焰图生成推荐 dwarf 方式。
4.4 perf report:可视化分析采样数据
perf report 读取 perf.data 文件,以交互式 TUI(终端用户界面)或文本格式展示采样结果,按热点函数排序,支持展开调用栈。
基本用法
# 交互式查看(默认 TUI 模式)
perf report
# 文本模式输出
perf report --stdio
# 指定输入文件
perf report -i my_perf.data
# 按调用链展开(显示子调用占比)
perf report --stdio --call-graph
# 只显示内核态符号
perf report --stdio --kallsyms=/proc/kallsyms
输出解读
文本模式输出示例:
# Samples: 1K of event 'cpu-clock'
# Event count (approx.): 1000000000
#
# Overhead Command Shared Object Symbol
# ........ ........... .................. ......................
#
35.67% my_program my_program [.] do_work
22.14% my_program libc-2.31.so [.] __memcpy_avx_unaligned
12.50% my_program [kernel.kallsyms] [k] __do_softirq
8.33% my_program my_program [.] parse_input
5.00% my_program [kernel.kallsyms] [k] tick_sched_timer
4.17% my_program my_program [.] free_buffer
3.33% my_program libc-2.31.so [.] malloc
2.08% my_program [kernel.kallsyms] [k] run_timer_softirq
1.67% my_program my_program [.] init_data
1.25% my_program [kernel.kallsyms] [k] update_process_times
| 列 | 含义 | 分析要点 |
|---|---|---|
| Overhead | 该符号占用的采样比例 | 比例越高,CPU 时间消耗越多 |
| Command | 进程名 | 区分不同进程的热点 |
| Shared Object | 符号所在的共享库或内核模块 | [k] 表示内核态,[.] 表示用户态 |
| Symbol | 函数名或符号名 | 结合调用栈可定位完整调用路径 |
内核性能分析要点:当
[kernel.kallsyms] 中的函数(如 __do_softirq、tick_sched_timer)出现在热点前列时,说明内核软中断或时钟处理消耗了大量 CPU,需要进一步分析中断来源或内核配置。
4.5 四命令协作流程
下图展示了从事件查询到数据采集、分析,再到火焰图生成的完整工作流:
4.6 常见问题与避坑指南
- 采样频率过高导致系统卡顿:全系统采样时,
-F 99是安全上限;若需更高频率,先在小范围测试开销。 - 调用栈不完整或显示为
[unknown]:检查程序是否编译时去除了帧指针(-fomit-frame-pointer),或尝试--call-graph dwarf。 - 内核符号无法解析:确保
/proc/kallsyms可读(需要 root 权限),或安装kernel-debuginfo包。 - perf.data 文件过大:使用
-m参数限制 mmap 缓冲区大小,或缩短采样时间。 - 虚拟化环境硬件事件缺失:部分云平台禁用 PMU 访问,此时只能使用软件事件和 tracepoint。
快速验证命令:执行
perf stat -e cycles,instructions,cache-misses ls /tmp,观察输出是否正常。若提示“event not found”,说明当前环境不支持该硬件事件,应改用软件事件或 tracepoint。
4.7 本章小结
perf 的四个核心命令构成了内核性能分析的基石:
- perf list 提供事件清单,是选择观测目标的起点。
- perf stat 给出聚合计数器,适合快速判断瓶颈类型(CPU、缓存、上下文切换)。
- perf record 以采样方式记录调用栈,是生成火焰图的数据源。
- perf report 展示热点函数及调用链,帮助定位具体代码路径。