火焰图 CPU 性能分析教程

火焰图(Flame Graph)是由 Brendan Gregg 发明的性能可视化方法,能够将 CPU 采样数据转化为直观的交互式图形。通过火焰图,你可以一眼看出哪些函数消耗了最多的 CPU 时间。本文将介绍在搬瓦工 VPS 上从数据采集到火焰图生成的完整流程。

一、火焰图的工作原理

火焰图的核心概念:

  • Y 轴:表示调用栈深度,从下到上是函数的调用链。
  • X 轴:按函数名字母排序,宽度代表该函数在采样中出现的比例。
  • 宽度:函数方块越宽,表示它消耗的 CPU 时间越多。
  • 颜色:随机的暖色系,仅用于视觉区分,不代表特殊含义。

最宽的"平台"就是性能瓶颈所在。

二、环境准备

# 安装 perf(数据采集工具)
apt update
apt install linux-tools-common linux-tools-$(uname -r) -y

# 下载 FlameGraph 工具集
git clone https://github.com/brendangregg/FlameGraph.git /opt/FlameGraph

# 添加到 PATH(可选)
echo 'export PATH=$PATH:/opt/FlameGraph' >> ~/.bashrc
source ~/.bashrc

三、CPU 火焰图生成

3.1 采集数据

# 全系统 CPU 采样 30 秒
perf record -F 99 -a -g -- sleep 30

# 针对特定进程采样
perf record -F 99 -p PID -g -- sleep 30

# 使用 DWARF 调用栈(更准确,适合没有帧指针的程序)
perf record -F 99 -p PID --call-graph dwarf -- sleep 30

3.2 生成火焰图

# 导出采样数据
perf script > out.perf

# 折叠调用栈
/opt/FlameGraph/stackcollapse-perf.pl out.perf > out.folded

# 生成 SVG 火焰图
/opt/FlameGraph/flamegraph.pl out.folded > cpu-flamegraph.svg

# 一条命令完成
perf script | /opt/FlameGraph/stackcollapse-perf.pl | /opt/FlameGraph/flamegraph.pl > cpu-flamegraph.svg

3.3 自定义火焰图样式

# 设置标题
/opt/FlameGraph/flamegraph.pl --title "Nginx CPU Profile" out.folded > nginx-cpu.svg

# 设置宽度
/opt/FlameGraph/flamegraph.pl --width 1200 out.folded > wide.svg

# 反向火焰图(从上到下,也叫冰柱图)
/opt/FlameGraph/flamegraph.pl --reverse out.folded > icicle.svg

# 过滤特定函数
grep "mysql" out.folded | /opt/FlameGraph/flamegraph.pl > mysql-only.svg

四、不同类型的火焰图

4.1 Off-CPU 火焰图

Off-CPU 火焰图显示进程被阻塞等待的时间分布,帮助发现 I/O、锁等待等问题。

# 使用 BPF 工具采集 Off-CPU 数据
apt install bpfcc-tools -y

# 采集 Off-CPU 数据
offcputime-bpfcc -df -p PID 30 > off-cpu.stacks

# 生成 Off-CPU 火焰图(使用蓝色系)
/opt/FlameGraph/flamegraph.pl --color=io --title "Off-CPU Time" off-cpu.stacks > offcpu.svg

4.2 内存分配火焰图

# 记录内存分配事件
perf record -e kmem:kmalloc -a -g -- sleep 10
perf script > mem.perf
/opt/FlameGraph/stackcollapse-perf.pl mem.perf > mem.folded
/opt/FlameGraph/flamegraph.pl --color=mem --title "Memory Allocation" mem.folded > memory.svg

4.3 差分火焰图

对比优化前后的性能变化:

# 采集优化前的数据
perf record -F 99 -a -g -- sleep 30
perf script > before.perf
/opt/FlameGraph/stackcollapse-perf.pl before.perf > before.folded

# 执行优化操作...

# 采集优化后的数据
perf record -F 99 -a -g -- sleep 30
perf script > after.perf
/opt/FlameGraph/stackcollapse-perf.pl after.perf > after.folded

# 生成差分火焰图
/opt/FlameGraph/difffolded.pl before.folded after.folded | \
  /opt/FlameGraph/flamegraph.pl > diff.svg

差分火焰图中红色表示性能恶化(时间增加),蓝色表示性能改善(时间减少)。

五、读图技巧

  • 找最宽的方块:这是 CPU 时间消耗最多的函数,优先优化。
  • 找宽阔的平台:函数自身(不含子函数)消耗大量 CPU 的地方。
  • 注意栈深度:过深的调用栈可能暗示递归或低效的抽象层。
  • 搜索功能:SVG 火焰图支持在浏览器中搜索函数名。
  • 点击缩放:点击某个函数可以将其放大为全宽查看细节。

六、不同语言的火焰图

Java 应用

# 使用 async-profiler
wget https://github.com/async-profiler/async-profiler/releases/latest/download/async-profiler-linux-x64.tar.gz
tar xzf async-profiler-linux-x64.tar.gz

# 生成火焰图
./async-profiler/bin/asprof -d 30 -f flamegraph.html PID

Node.js 应用

# 使用 0x 工具
npm install -g 0x
0x my-app.js

# 或使用 perf + --perf-basic-prof 标志
node --perf-basic-prof my-app.js &
perf record -F 99 -p $! -g -- sleep 30

Python 应用

# 安装 py-spy
pip install py-spy

# 生成火焰图
py-spy record -o profile.svg --pid PID --duration 30

七、自动化采集脚本

cat > /usr/local/bin/flame-profile.sh <<'EOF'
#!/bin/bash
DURATION=${1:-30}
OUTPUT=${2:-"flamegraph-$(date +%Y%m%d-%H%M%S).svg"}
FLAMEGRAPH_DIR="/opt/FlameGraph"

echo "Profiling for ${DURATION} seconds..."
perf record -F 99 -a -g -- sleep "$DURATION"

echo "Generating flame graph..."
perf script | \
  "$FLAMEGRAPH_DIR/stackcollapse-perf.pl" | \
  "$FLAMEGRAPH_DIR/flamegraph.pl" --title "CPU Profile (${DURATION}s)" > "$OUTPUT"

echo "Flame graph saved to: $OUTPUT"
echo "Open in browser: python3 -m http.server 8080"
EOF
chmod +x /usr/local/bin/flame-profile.sh

# 使用:采集 60 秒数据
flame-profile.sh 60 my-profile.svg

总结

火焰图是定位 CPU 性能瓶颈最直观有效的方法,建议与 perf 工具 配合使用。对于更动态的追踪需求可以使用 BPFtrace,系统调用层面的分析可以使用 strace。选购搬瓦工 VPS 请查看 全部方案,购买时使用优惠码 NODESEEK2026 可享受 6.77% 的折扣,通过 bwh81.net 访问官网。

关于本站

搬瓦工VPS中文网(bwgvps.com)是非官方中文信息站,整理搬瓦工的方案、优惠和教程。我们不销售主机,不提供技术服务。

新手必读
搬瓦工优惠码

NODESEEK2026(优惠 6.77%)

购买时填入即可抵扣。