背景:
为了查询应用运行卡顿的原因,使用perf工具查找哪几个函数占用了较多的CPU资源,然后优化占用CPU资源最多的几个函数。
Perf工具简介
Perf是Linux内核提供的性能分析工具,能够监控CPU性能计数器、跟踪内核和用户态事件,帮助定位热点函数、缓存命中率等问题。它支持多种分析模式,如采样(sampling)、统计(counting)和追踪(tracing)。
安装Perf工具
在大多数Linux发行版中,Perf可通过包管理器安装:
- Debian/Ubuntu:
sudo apt install linux-tools-common linux-tools-$(uname -r)
- RHEL/CentOS:
sudo yum install perf
如果遇到版本兼容性问题,需确保内核头文件与当前运行的内核版本一致。
基本使用流程
1. 采样CPU事件
通过perf record
采集CPU执行样本,默认监控cycles
(CPU时钟周期)事件:
sudo perf record -F 99 -g -p <PID> # -F 99表示每秒采样99次,-g启用调用栈,-p指定进程ID
sudo perf record -F 99 -g -a # 监控所有CPU
运行结束后生成perf.data
文件。
2. 生成分析报告
使用perf report
解析采样数据:
sudo perf report -n --stdio # 文本模式查看
sudo perf report -g # 图形化交互模式
报告会显示热点函数及其调用栈,按CPU占用百分比排序。
3. 统计事件计数
直接统计特定事件的发生次数(不生成详细样本):
sudo perf stat -e cycles,instructions,cache-misses -p <PID>
高级功能
火焰图生成
- 使用
perf script
导出采样数据:sudo perf script > out.perf
- 通过FlameGraph工具生成SVG火焰图:
git clone https://github.com/brendangregg/FlameGraph ./FlameGraph/stackcollapse-perf.pl out.perf | ./FlameGraph/flamegraph.pl > flame.svg
追踪特定函数
监控内核或用户态函数的调用:
sudo perf probe --add 'schedule' # 添加内核函数追踪点
sudo perf trace -e probe:schedule -p <PID> # 追踪调用
硬件事件监控
Perf支持多种硬件性能计数器(PMC):
sudo perf record -e branch-misses,LLC-load-misses -a # 监控分支预测失败、LLC未命中
常见问题
符号表缺失
若报告中函数名显示为十六进制地址,需确保调试符号已安装:
- 对于应用程序:编译时添加
-g
选项。 - 对于内核:安装
dbgsym
包(Debian)或debuginfo
包(RHEL)。
权限问题
部分性能事件需要CAP_PERFMON
或root
权限,可通过以下命令临时授权:
sudo sysctl kernel.perf_event_paranoid=-1
多线程分析
结合-t
选项监控特定线程:
sudo perf record -t <TID> -g -e cycles
示例输出解读
perf report
的典型输出片段:
60.12% program libc.so.6 [.] malloc
|
--- malloc
|
--50.2%-- foo
bar
表示malloc
占用了60.12%的CPU时间,其中50.2%由foo
->bar
调用路径触发。
注意事项
- 采样频率过高(如
-F 1000
)可能导致显著性能开销。 - 内核版本差异可能导致部分功能不可用(如eBPF集成)。
- 虚拟机环境可能限制硬件性能计数器的访问。
通过合理配置事件和采样频率,Perf能够高效定位CPU热点,为性能优化提供数据支撑。
嵌入式工作中需要注意的是,如果终端控制台敲perf命令显示没有这个命令,那么需要自己拉源码编译然后下载到机器中,同时也需要修改内核配置,make kernel_menuconfig->Enable performance events and counters,这是因为 perf
依赖于内核的 perf_events
子系统来采集性能数据,如果内核没有编译支持这个功能,perf
就会报错。
内核未支持,敲perf会报类似的错误:
perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error 38 (Function not implemented)
...
No CONFIG_PERF_EVENTS=y kernel support configured?
最后总结下常见的perf命令:
perf stat
perf stat用于统计程序运行时的性能事件,如CPU周期、缓存命中率等。示例:
perf stat -e cycles,instructions,cache-misses ./your_program
perf record
perf record用于记录程序运行时的性能数据,生成perf.data文件。示例:
perf record -g ./your_program
perf report
perf report用于分析perf record生成的数据文件。示例:
perf report -n --stdio
perf top
perf top实时显示系统或进程的性能事件,类似于top命令。示例:
perf top -e cycles
perf list
perf list列出当前系统支持的所有性能事件。示例:
perf list
perf annotate
perf annotate对特定函数进行代码级性能分析。示例:
perf annotate -s function_name
perf script
perf script将perf.data转换为可读文本或其他格式。示例:
perf script -F comm,pid,time,event
perf trace
perf trace跟踪系统调用和信号。示例:
perf trace -e nanosleep ./your_program
perf probe
perf probe动态添加跟踪点。示例:
perf probe --add 'schedule'
perf mem
perf mem分析内存访问性能。示例:
perf mem record ./your_program