火焰图简介
火焰图是一种性能分析的可视化工具,它将CPU的调用栈(Call Stack)信息以矩形火焰的形式展现出来。
Y轴:代表调用栈的深度(函数A调用了函数B,B就叠在A上面)。
X轴:代表CPU的抽样次数。一个函数在X轴上占据的宽度越长,就代表它(或它调用的子函数)消耗的CPU时间越多。
我们的目标就是找到那些又宽又平的“火焰山顶”,它们就是CPU占用过高的元凶。
流程一:准备工作 (安装工具与依赖)
我们需要安装 perf
工具、从GitHub上下载火焰图的生成脚本,并且为了分析内核函数,还需要安装内核的调试符号。
1.安装 perf
工具
在 CentOS 7 上:
sudo yum install perf -y
在 Ubuntu 上:
sudo apt update
sudo apt install linux-tools-common linux-tools-$(uname -r) -y
2.安装内核调试符号 (非常关键!) 没有这个,您在火焰图里看到的内核函数名将是一堆看不懂的内存地址。
在 CentOS 7 上:
首先需要启用debuginfo仓库:
sudo yum install -y yum-utils
sudo debuginfo-install --enablerepo=base-debuginfo kernel-$(uname -r)
如果找不到,可能需要编辑 /etc/yum.repos.d/CentOS-Debuginfo.repo
文件,将 enabled=0
改为 enabled=1
。
在 Ubuntu 上:
需要添加一个专门的ddebs
仓库:
# 此处以
sudo tee /etc/apt/sources.list.d/ddebs.list << EOF
deb http://ddebs.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse
deb http://ddebs.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com/ $(lsb_release -cs)-proposed main restricted universe multiverse
EOFsudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C8CAB6595FDFF622
sudo apt update
sudo apt install linux-image-$(uname -r)-dbgsym -y
3.下载火焰图生成脚本 这是由性能大神Brendan Gregg开发的Perl脚本集。
# 安装 git
sudo yum install git -y # CentOS
# sudo apt install git -y # Ubuntugit clone https://github.com/brendangregg/FlameGraph.git
cd FlameGraph
(这些是Perl脚本,Linux系统通常已自带Perl解释器,无需额外安装)
流程二:采集性能数据
现在,我们使用 perf
来记录一段时间内系统范围的CPU调用栈信息。
检查权限设置(可选) 查看 perf_event_paranoid
的设置,如果值大于1,可能会限制非root用户使用perf。我们用sudo
运行,通常没问题。
cat /proc/sys/kernel/perf_event_paranoid
执行 perf record
命令 在复现CPU占用过高的场景时,执行以下命令,让它在后台采集60秒的数据。
# -F 99: 以99赫兹的频率采样CPU(避免与系统定时器同步)
# -a: 采集所有CPU
# -g: 记录调用图(调用栈)
# --call-graph dwarf: 使用DWARF格式记录调用栈,对内核函数分析更准确
# sleep 60: 让perf持续采集60秒。在这60秒内,您需要尽量让问题复现。
sudo perf record -F 99 -ag --call-graph dwarf -- sleep 60
命令执行结束后,当前目录下会生成一个名为 perf.data
的文件,这就是我们的原始数据。
流程三:生成火焰图
我们使用FlameGraph目录下的两个脚本,分两步处理 perf.data
文件。
折叠调用栈 (Collapse Stacks) 此步骤将 perf
的输出转换成火焰图脚本认识的格式。
# 确保您当前在 FlameGraph 目录下
sudo perf script | ./stackcollapse-perf.pl > out.perf-folded
执行后会生成一个 out.perf-folded
文件。
生成SVG火焰图 这是最后一步,将折叠后的数据渲染成一个可交互的SVG图片。
./flamegraph.pl out.perf-folded > kernel_cpu.svg
执行后,您会得到一个名为 kernel_cpu.svg
的文件。这就是最终的火焰图!
流程四:交互式分析
查看火焰图 将生成的 kernel_cpu.svg
文件从虚拟机中下载到您本地的电脑上(可以通过Termius的SFTP功能或scp
命令)。然后,用您的网页浏览器(如Chrome或Firefox)打开它。
如何解读与交互
看宽度:火焰图从下往上看。最底层的 all
代表总采样。越往上,函数调用栈越深。任何一层,一个函数方块的宽度代表了它在CPU上出现的时间占比。我们的目标就是寻找那些顶层“又宽又平”的山顶(plateau)。
看颜色:颜色本身没有特殊含义,只是为了区分不同的函数。
交互-悬停:将鼠标悬停在任何一个方块上,浏览器左下角会显示完整的函数名、采样占比等详细信息。
交互-点击:这是最重要的交互! 当您点击任何一个方块时,整个火焰图会以此方块为顶层进行“缩放”,让您能清晰地看到是哪些子函数导致了这个函数的CPU占用。您可以层层深入,探究问题的根源。
分析内核态CPU占用过高时,您需要重点关注那些函数名中带有 [k]
标记、或者名字是内核API(如copy_page
, ext4_
, tcp_
, schedule
, kvm_
等)的宽大方块。 通过点击它们,您就能追溯出是哪个系统调用路径导致了大量的内核CPU消耗。