本文总结了在 Linux (CentOS) 环境下,使用 perf 工具进行服务端程序性能瓶颈排查的完整流程。涵盖了从实时 CPU 监控到生成全局火焰图(Flame Graph)的标准操作步骤。
一、环境准备
1.安装perf工具
bash
yum install -y perf
验证安装:执行perf --version查看版本号。
2.获取FlameFraph工具链
由于 CentOS 环境下直接访问 GitHub 可能受限,建议从 Gitee 镜像克隆 Brendan Gregg 开源的火焰图生成脚本:
bash
cd ~
git clone https://gitee.com/mirrors/FlameGraph.git
3.测试程序test.cpp
cpp
#include <pthread.h>
void func_d()
{
int i;
for(i=0;i<50000;i++);
}
void func_a()
{
int i;
for(i=0;i<100000;i++);
func_d();
}
void func_b()
{
int i;
for(i=0;i<200000;i++);
}
void func_c()
{
int i;
for(i=0;i<300000;i++);
}
void* thread_fun(void* param)
{
while(1) {
int i;
for(i=0;i<100000;i++);
func_a();
func_b();
func_c();
}
}
int main(void)
{
pthread_t tid1,tid2;
int ret;
ret=pthread_create(&tid1,NULL,thread_fun,NULL);
if(ret==-1){
}
ret=pthread_create(&tid2,NULL,thread_fun,NULL);
if(pthread_join(tid1,NULL)!=0){
}
if(pthread_join(tid2,NULL)!=0){
}
return 0;
}
编译输出
bash
g++ test.cpp -pthread
二、实时监控:perf top
1.获取目标进程PID
使用 ps 和 grep 查找目标服务的进程号:
bash
ps -ef | grep a.out

2.启动实时监控
bash
perf top -p <PID>

Overhead:该函数占用 CPU 时间的百分比。
Shared Object:归属模块(如 [kernel] 代表 Linux 内核,srs 代表业务代码)。
Symbol:具体的函数名称(如 finish_task_switch 为内核上下文切换,空载时极高;高负载时应关注业务相关的编解码函数)。
三、数据采样:perf record
当问题难以复现或需要分析深层调用链时,必须使用 perf record 将一段时间内的 CPU 采样数据录制到硬盘上,为生成火焰图做准备。
标准录制命令:
bash
perf record -F 99 -p <PID> -g -- sleep 10
-F 99:采样频率。设定为每秒 99 次而不是 100 次,是为了避免与操作系统定时任务产生"同频共振"导致数据失真。
-p :指定录制的目标进程。
-g:关键参数! 开启 Call-graph(调用栈)记录,抓取完整的"谁调用了谁"的关系链,这是生成火焰图的刚需。
-- sleep 10:让程序录制 10 秒后自动停止并退出,避免手动 Ctrl+C 导致数据损坏。
执行完毕后,当前目录下会生成一个 perf.data 二进制文件。
四、生成并查看火焰图
将生成的 perf.data 转化为直观的 SVG 格式火焰图,需要利用 Linux 的管道符(|)和重定向符(>)将三道工序串联起来。
bash
perf script | ~/FlameGraph/stackcollapse-perf.pl | ~/FlameGraph/flamegraph.pl > srs_flame.svg
perf script:读取底层的 perf.data 二进制文件,翻译成带时间戳和调用栈的明文文本。
stackcollapse-perf.pl:折叠并合并调用栈数据,统计每个调用链路发生的次数。
flamegraph.pl:根据统计次数计算宽度,渲染出带有颜色的 SVG 代码。
srs_flame.svg:将最终生成的 SVG 源代码写入文件保存。
