flamegraph

把采样调用栈折叠成 SVG 火焰图,定位 CPU 与阻塞热点

补充说明

火焰图不是采集器,而是把 perf、eBPF 或语言级 profiler 采到的调用栈按“栈帧出现次数”聚合后绘制的 SVG。横向宽度表示采样占比,不是耗时绝对值;纵向是调用栈深度。常见输入有 perf record -g、bpftrace 以及 async-profiler/py-spy 的折叠栈。

常用示例

# 以 99Hz 采样目标进程 30 秒,-g 采集调用栈
sudo perf record -F 99 -g -p <PID> -o /tmp/perf.data -- sleep 30

# 把 perf.data 折叠并生成 SVG(FlameGraph 仓库路径按实际修改)
sudo perf script -i /tmp/perf.data | \
  /opt/FlameGraph/stackcollapse-perf.pl | \
  /opt/FlameGraph/flamegraph.pl --title "CPU flame graph" > /tmp/cpu.svg

# Java 进程:async-profiler 3.x 用 asprof 直接输出交互式 HTML
asprof -d 30 -e cpu -f /tmp/java.html <PID>

# Python 进程:py-spy 采样并直接生成 SVG
sudo py-spy record -o /tmp/python.svg --pid <PID>

# 先确认符号是否可解析,避免整张图都是 [unknown]
sudo perf report -i /tmp/perf.data --stdio | head -20

perf script report flamegraph 在较新的 perf 中也能直接生成 HTML,但各发行版版本差异较大;生产上更常用上面的折叠脚本。

易错点与排错

读完自测

  1. 火焰图的横向宽度代表什么,能否直接读成“函数耗时 3 秒”?
  2. 为什么 on-CPU 火焰图找不到阻塞类热点?
  3. perf record 忘记加 -g 会发生什么?
答案
  1. 宽度是采样占比,同一层可以横向比较,但不能跨层直接换算成绝对耗时。
  2. 阻塞或睡眠的线程不在 CPU 上执行,不会被 on-CPU 采样命中;需要 off-CPU 或 wall-clock 采样。
  3. 没有调用栈,只剩单帧函数名,火焰图无法展示调用关系。

相关条目