Perf 工具深度解析
Perf (Performance Counters for Linux)是 Linux 系统的性能分析工具,基于内核的 perf_event
子系统,通过硬件性能计数器(PMC)、软件事件和跟踪点(tracepoints)实现全方位性能监控。
一、工作原理与实现机制
1. 核心组件
组件 | 作用 |
---|---|
硬件性能计数器 | 利用 CPU 的 PMU(Performance Monitoring Unit)统计指令周期、缓存命中/失效等事件。 |
软件事件 | 内核插桩统计上下文切换、缺页异常等软件行为(如 context-switches )。 |
跟踪点 | 静态内核探针(如 sched:sched_switch ),记录特定代码路径的执行信息。 |
kprobes/uprobes | 动态内核/用户空间探针,支持自定义函数级跟踪。 |
2. 数据采集流程
plaintext
+----------------+ +-------------------+ +-----------------+
| 配置事件 | ----> | perf_event_open() | ----> | 内核事件子系统 |
| (cycles, cache | | (系统调用) | | (PMU/软件计数器) |
| misses, etc.) | +-------------------+ +-----------------+
+----------------+ |
v
+------------------+ mmap() +--------------+
| 用户空间工具 | <------------- | 环形缓冲区 |
| (perf record/stat)| | (存储样本) |
+------------------+ +--------------+
3. 关键机制
- 环形缓冲区:采样数据通过无锁环形缓冲(避免系统调用开销)传递到用户空间。
- 采样模式 :
- 计数模式 :累计事件发生次数(
perf stat
)。 - 中断采样 :事件达到阈值时触发中断,记录指令指针/IP(
perf record
)。
- 计数模式 :累计事件发生次数(
- 符号解析 :通过
/proc/kallsyms
或 ELF 文件将地址映射为函数名。
二、命令大全与使用示例
1. 常用命令总结
命令 | 功能 | 常用选项 |
---|---|---|
perf stat |
统计事件发生的绝对次数 | -e (指定事件), -p (PID), -a (全局) |
perf record |
采样并保存数据到 perf.data |
-g (调用栈), -F (采样频率), -o (输出文件) |
perf report |
解析 perf.data 生成报告 |
--stdio (文本报告), -n (显示样本数) |
perf top |
实时显示热点函数 | -e (事件), -K (隐藏内核符号) |
perf list |
列出支持的事件 | --details (显示事件详情) |
perf script |
导出采样数据为脚本格式 | -i (输入文件), -F (自定义字段) |
perf trace |
类似 strace ,跟踪系统调用 |
-p (PID), -e (过滤系统调用) |
perf annotate |
汇编代码级注解 | --stdio (文本模式), -s (符号) |
2. 详细示例
Perf 典型使用场景及命令详解
2.1 CPU 性能分析
场景 | 命令示例 | 说明 |
---|---|---|
CPU 热点函数分析 | perf top -e cycles -p <PID> |
实时查看进程的热点函数 |
调用链分析 | perf record -F 99 -g -p <PID> -o perf.data; perf report --stdio |
记录调用栈并生成文本报告 |
多核负载均衡分析 | perf stat -e sched:sched_migrate_task -a sleep 10 |
监控任务在 CPU 核间的迁移情况 |
IPC 指标分析 | perf stat -e cycles,instructions -p <PID> -- sleep 5 |
计算指令/周期比 (IPC = instructions/cycles) |
示例:CPU 瓶颈诊断
bash
# 1. 查找 CPU 占用最高的进程
perf top
# 2. 对高负载进程 (PID 1234) 进行采样
perf record -F 997 -g -p 1234 -o cpu_hotspot.data -- sleep 30
# 3. 生成带调用栈的报告
perf report -i cpu_hotspot.data --stdio --no-children
输出片段:
# Overhead Command Shared Object Symbol
# ........ ....... ................ ................................
#
62.15% nginx nginx [.] ngx_http_process_request
|
---ngx_http_process_request
|
|--45.32%-- ngx_http_core_content_phase
| ngx_http_proxy_handler
| |
| |--38.71%-- ngx_http_upstream_connect
| | __connect
2.2 内存子系统分析
场景 | 命令示例 | 说明 |
---|---|---|
缓存命中率分析 | perf stat -e cache-references,cache-misses <command> |
统计 L1/L2/L3 缓存效率 |
内存带宽分析 | perf stat -e uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ |
监控 DDR 内存读写带宽 (需 Intel PMU) |
缺页异常分析 | perf stat -e page-faults,minor-faults,major-faults -p <PID> |
区分次/主缺页异常 |
示例:内存敏感型应用优化
bash
# 1. 检测缓存效率
perf stat -e \
L1-dcache-load-misses,LLC-load-misses,dTLB-load-misses \
./memory_intensive_app
# 2. 输出结果
35,421,632 L1-dcache-load-misses # 12.45% of all L1-dcache hits
8,765,432 LLC-load-misses # 3.21% of all LL-cache hits
1,234,567 dTLB-load-misses # 0.45% of all dTLB cache hits
2.3 I/O 性能分析
场景 | 命令示例 | 说明 |
---|---|---|
块设备 I/O 延迟 | perf record -e block:block_rq_issue,block:block_rq_complete -a |
跟踪块设备请求生命周期 |
文件系统操作跟踪 | perf record -e ext4:*,xfs:* -a |
捕获特定文件系统事件 |
系统调用分析 | perf trace -e 'read,write,openat' -p <PID> |
监控文件相关系统调用 |
示例:磁盘 I/O 瓶颈诊断
bash
# 1. 跟踪块设备事件
perf record -e block:block_rq_issue -e block:block_rq_complete -a
# 2. 生成延迟报告
perf script | awk '/block_rq_issue/{ts[$5]=$4}/block_rq_complete/{if(ts[$5])printf "%.2f ms\n", ($4-ts[$5])*1000}'
输出:
8.23 ms # I/O 请求延迟
12.45 ms
5.67 ms
2.4 网络性能分析
场景 | 命令示例 | 说明 |
---|---|---|
网络协议栈跟踪 | perf record -e skb:kfree_skb -e net:net_dev_xmit -a |
监控丢包和发送事件 |
TCP 函数跟踪 | perf probe --add tcp_v4_connect; perf record -e probe:tcp_v4_connect |
动态跟踪 TCP 连接建立 |
网络延迟分析 | perf trace -e sendto,recvfrom -p <PID> -T |
跟踪网络收发系统调用时间戳 |
示例:网络丢包分析
bash
# 1. 创建丢包检测探针
sudo perf probe --add 'kfree_skb reason'
# 2. 记录丢包事件
sudo perf record -e probe:kfree_skb -aR -o net_drop.data
# 3. 分析丢包原因
sudo perf script -i net_drop.data | awk '{print $5}' | sort | uniq -c | sort -nr
输出:
1423 TCP: Too many orphaned sockets
890 NETDEV WATCHDOG: enp0s3 transmit timeout
321 ICMP: Destination unreachable
2.5 锁与同步分析
场景 | 命令示例 | 说明 |
---|---|---|
锁竞争分析 | perf record -e lock:lock_acquire -e lock:lock_release -g -p <PID> |
跟踪锁获取/释放事件 |
调度延迟分析 | perf sched record -p <PID>; perf sched latency |
分析任务调度延迟 |
中断分析 | perf record -e irq:irq_handler_entry -e irq:irq_handler_exit -a |
跟踪中断处理时间 |
示例:锁竞争诊断
bash
# 1. 记录锁事件
perf record -e lock:lock_acquire -e lock:lock_release -g -p 5678 -o locks.data
# 2. 生成竞争报告
perf lock report -i locks.data --combine-locks --sort contended
输出:
Name acquired contended avg wait (ns)
----------------------------------------------------------
&sb->s_type->i_lock 14235 4231 15234
&rq->lock 8765 2109 8765
mm->page_table_lock 6543 987 5432
2.6 火焰图生成
bash
perf record -F 99 -a -g -- sleep 30
perf script > out.perf
./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
./FlameGraph/flamegraph.pl out.folded > flame.svg
2.7 Perf 工作流程图
CPU 瓶颈 内存瓶颈 I/O 瓶颈 网络问题 锁竞争 确定分析目标 性能问题类型 perf record/top perf stat -e cache perf trace -e block perf probe + net events perf lock 生成火焰图/报告 缓存命中率报告 I/O 延迟直方图 丢包原因统计 锁竞争分析 优化热点函数 调整数据布局 优化 I/O 模式 调整网络参数 减少锁粒度
2.8 高级技巧
-
PEBS 精确采样
bashperf record -e cycles:pp -c 1000000 -p <PID> # 每100万周期采样一次
-
事件分组统计
bashperf stat -e '{cycles,instructions,branch-misses}' -r 5 ./program
-
时间戳跟踪
bashperf record -e sched:sched_switch -T -a -- sleep 10 perf script --ns
-
跨进程跟踪
bashperf record -e 'sched:sched_wakeup,sched:sched_switch' -a
-
用户空间探针
bashperf probe -x /path/to/bin 'func_name' perf record -e probe_bin:func_name -a
三、Perf 使用流程图
计数模式 采样模式 实时模式 动态跟踪 启动分析 选择模式 perf stat perf record 保存到 perf.data perf report/report 生成文本/图形报告 perf top perf probe + record perf script 分析日志 优化代码/系统
四、高级技巧
-
事件修饰符 :
u
:仅用户空间,如perf stat -e cycles:u
k
:仅内核空间
-
精确采样 :
bashperf record -e cycles:pp -p 1234 # 使用 PEBS 精确采样
-
多事件分析 :
bashperf stat -e cycles,instructions,cache-references,cache-misses ls
五、注意事项
- 权限要求 :部分事件需要
CAP_PERFMON
或root
权限。 - 符号表 :用户程序需编译时添加
-g
选项(保留调试符号)。 - 内核版本 :不同内核版本支持事件可能不同(
perf list
查看)。
通过灵活组合命令,Perf 可定位 CPU 瓶颈、内存延迟、I/O 问题等,是 Linux 性能调优的核心工具。