火焰圖簡介
火焰圖是一種性能分析的可視化工具,它將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消耗。