1 perf 简介
perf是 Linux 内核自带的性能分析工具,基于内核的 Performance Monitoring Unit(PMU)实现。它能够收集CPU、缓存、分支预测等硬件事件,以及内核和用户空间的各种软件事件。perf 支持采样(Sampling)、统计(Counting)、调用栈追踪(Call Graph)等多种模式。适用于性能瓶颈定位、热点函数分析、系统级调优等多种场景。
1.1 主要功能
统计性能事件(CPU使用率、缓存命中率等)
采样函数调用栈,定位热点代码
分析系统性能(进程、线程、内核模块等)
生成可视化报告
1.2 工作原理
perf 通过内核暴露的 perf_event_open 系统调用,与硬件PMU或内核 tracepoint 交互,收集事件数据。核心流程如下:
用户启动 perf ,指定监控事件和目标对象;
perf 设置事件监控,内核开始统计或采样;
事件触发时,相关数据被记录到内核缓冲区;
perf 工具从内核读取数据,生成报告或可视化结果。
1.3 核心概念
事件(Event)。分为硬件事件(cycles、instructions、cache-misses等)、软件事件(page-faults、context-switches等)、自定义 tracepoint。
统计(Counting)。记录事件发生的总次数,时和整体性能评估。
采样(Sampling)。定期或按事件阈值采集程序状态,用于热点定位。
调用栈(Call Graph)。perf 支持内核和用户空间的调用栈采集,帮助分析函数间的调用关系和耗时分布。
PMU(Performance Monitoring Unit)。现代CPU内置PMU,能高效统计低级硬件指令。perf通过PMU获取这些数据。
2 安装
先检查当前系统是否有 perf 工具:perf --version
如果没有则运行指令安装:
sudo apt update
sudo apt install linux-tools-common linux-tools-$(uname -r)3 使用
3.1 perf stat —— 性能事件统计
统计程序运行期间的各种事件,时和宏观性能对比。
示例:
sudo perf stat -e cycles,instructions,cache-misses ./your_program-e:指定要统计的事件
cycles:CPU时钟周期数
instructions:执行的指令数
cache-misses:缓存未命中次数
3.2 perf record/report —— 采样/报告
采样(record):采集程序运行时的采样数据(如PC、调用栈)。
报告(report):对采样数据进行分析,展示热点函数、调用栈等信息。
测试代码:
#include <vector>
#include <iostream>
int ComputeSum(const std::vector<int>& data) {
int sum = 0;
for (int v : data) {
sum += v;
}
return sum;
}
int main() {
std::vector<int> numbers(10000000, 1);
std::cout << "Sum: " << ComputeSum(numbers) << std::endl;
return 0;
}编译并采样:
g++ -g -O2 test-demo.cc -o test-demo
sudo perf record ./test-demo
sudo perf report报告内容:
%:该符号在采样中的比例
Symbol:函数名
Shared Pbject:代码所在文件/库
分析长期运行的服务进程:
sudo perf record -p <pid> -g
sudo perf report全系统采样,适合排查系统级性能瓶颈:
sudo perf record -a -g
sudo perf report3.3 perf top —— 实时热点分析
实时显示当前系统或进程的热点函数
3.4 函数调用栈分析
sudo perf record -g ./your_program
sudo perf report-g:开启调用栈采集,报告中可以查看函数之间的调用路径
-F <NUMBER>:指定采集频率,默认频率为 4000Hz
-p <PID>:指定进程
-t <TID>:指定线程
4 可视化 —— 火焰图(Flame Graph)
火焰图基于采样调用栈(如perf record -g采集的数据),统计各个调用路径出现的次数。每条“火焰”宽度表示耗时,层级表示调用链。
对某个程序采样:
sudo perf record -F 99 -g ./your_program
// -F 99 设置采样频率为99Hz
// -g 采集调用栈(Call Graph)对整个系统采样:
sudo perf record -F 99 -a -g
// -a 表示全系统采样采样后会生成 perf.data 文件,包含所有采样点的调用栈信息。
4.1 安装 FlameGraph 工具
FlameGraph 是一套Perl脚本,需要从github上克隆到本地。
下载:
git clone https://github.com/brendangregg/FlameGraph.git4.2 火焰图生成步骤
1 使用 perf 采集调用栈数据
sudo perf record -F 99 -g ./your_program2 生成脚本数据
sudo perf script -i /path/to/perf.data > out.perl3 折叠调用栈
进入 FlameGraph 目录:
。4 生成 SVG 火焰图
./flamegraph.pl out.folded > flamegraph.svg步骤2,3,4可以使用管道连接:
sudo perf script -i /path/to/perf.data | ./stackcollapse-perf.pl | ./flamegraph.pl > flamegraph.svg
评论区