火焰图分析cpu热点只需三步:采样、转换、画图;关键在真实采样和识别最宽“火焰尖顶”,即耗时最多的函数。需perf与flamegraph脚本配合,精准针对进程采样并带-g选项保留调用栈,最后生成svg交互查看宽度(时间占比)与顶层(执行现场)。

直接用火焰图看CPU热点函数,核心就三步:采样、转换、画图。关键不在工具多难,而在于采样是否真实反映负载,图形是否能一眼锁定最宽的“火焰尖顶”——那通常就是拖慢整个程序的罪魁祸首。
环境准备:perf和FlameGraph脚本缺一不可
perf是内核自带的采样引擎,必须匹配当前运行的内核版本:
- Ubuntu/Debian:运行 sudo apt install linux-tools-$(uname -r) linux-tools-common,别只装 generic 版本,否则可能缺少符号支持
- CentOS/RHEL:用 sudo yum install perf 即可,但需确认内核启用了 CONFIG_PERF_EVENTS
- 装完验证:perf --version 和 sudo perf record -F 99 -g sleep 1 能成功生成 perf.data 就算过关
- 接着克隆官方脚本:git clone https://github.com/brendangregg/FlameGraph.git,重点要用里面的 stackcollapse-perf.pl 和 flamegraph.pl
精准采样:让perf抓到你关心的那段“忙”
不要盲目全局采样。针对具体进程,推荐两种可靠方式:
- 启动时直接记录:sudo perf record -F 99 -g -- ./your-program arg1 arg2,适合可复现的短任务
- 对已运行进程追加采样:sudo perf record -F 99 -g -p $(pidof your-program) --sleep 20,适合后台服务或长时进程
- 加 -F 99 是标准频率,太高会扰动系统,太低可能漏掉瞬态热点
- 务必带 -g,否则看不到调用栈,火焰图就只剩一层,失去分析价值
生成与解读:宽度即时间,顶层即现场
采样完成后,执行三行命令即可出图:
- perf script > out.stacks(把二进制数据转为文本调用栈)
- ./stackcollapse-perf.pl out.stacks > folded.stacks(合并重复栈路径)
- ./flamegraph.pl folded.stacks > cpu-flame.svg(生成可交互SVG)
打开 svg 文件后,注意三点:
- 横轴宽度 = 该函数被采样次数占比 → 宽度最大者,就是CPU花时间最多的地方
- 纵轴从下往上是调用关系 → 最顶层函数是当前正在执行的,它下面层层是它的调用者
- 鼠标悬停能看到具体样本数和百分比,比如 cairo_show_text(1428 samples, 32.1%),说明文字渲染占了近三分之一CPU时间
常见陷阱与绕过方法
实际操作中容易卡在几个地方:
- Permission denied:非root用户默认无权访问 perf_event,临时解决:echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
-
函数名显示为 [unknown]:说明缺少调试符号,编译程序时加 -g,或安装对应 debuginfo 包(如 ubuntu 的
your-program-dbgsym) - 火焰图太平、没明显尖顶:可能是采样时间太短或负载不稳,延长 --sleep 至 30 秒以上,或多次运行取平均
- 想对比优化前后差异:用 flamegraph.pl --diff 生成差分图,红色收缩、绿色扩张,变化一目了然











