Linux使用perf分析CPU占用情況的方法步驟
1. 如何使用perf工具
1.1 perf安裝
perf安裝命令:
sudo apt-get install linux-tools-$(uname -r) linux-tools-generic -y sudo apt-get install linux-tools-$(uname -r) linux-tools-generic -y --fix-missing perf -v # 查看perf版本
1.2 首次使用perf報錯
No permission to enable cycles: u event

解決方法:直接修改 /proc/sys/kernel/perf_event_paranoid,按照報錯提示修改為 -1
如果是docker容器環(huán)境提示 read only file system, 新建容器的時候應(yīng)該添加 privileged=true 賦予權(quán)限
1.3 添加測試程序
新建并添加測試程序如下,輸入代碼
touch main.cpp vim main.cpp
#include <iostream>
using namespace std;
void delay()
{
int i,j;
for(i = 0; i < 1000000; i++)
j=i;
}
void function_1()
{
int i;
for(i=0 ; i < 10; i++)
delay();
}
void function_2()
{
int i;
for(i = 0; i< 30; i++)
delay();
}
int main(void)
{
std::cout << "begin: " << std::endl;
function_1();
function_2();
std::cout << "end!" << std::endl;
}
1.4 編譯并執(zhí)行指令生成perf.data文件
編譯測試程序
g++ main.cpp -o main
生成perf.data
sudo perf record ./main

1.5 添加-g選項能查看call graph調(diào)用信息
添加-g選項查看調(diào)用信息
sudo perf record -g ./main
1.6 查看perf.data
生成熱點(diǎn)函數(shù)占用CPU的比例
perf report

可以看到, 程序中main函數(shù)總體CPU資源占比(CPU時間片)97.85%, 其中delay函數(shù)占比97.59%, function_1和function_2的占比占比近7:3
1.7 perf工作流

1.8 sudo perf record -F 99 -p 2512 -g – sleep 60
- record: 表示采集系統(tǒng)事件,沒有采用-e執(zhí)行采集事件,則默認(rèn)采用CPU時鐘周期
- -F: 指定采樣頻率, 可以設(shè)置99, 1000等等, -F 99表示每秒采樣99次, 如果99次都是同一函數(shù), 說明CPU在這1s內(nèi)都在執(zhí)行這一函數(shù), 可能存在性能問題. 頻率越高,perf record獲得的樣本數(shù)量也會越多,分析結(jié)果會更加精細(xì),但采樣會使程序的運(yùn)行變慢,因此需要根據(jù)具體情況選擇合適的采樣頻率; 默認(rèn)頻率4000Hz

- -p: 指定進(jìn)程號, 對某一進(jìn)程進(jìn)行分析
- -g: 表示記錄調(diào)用棧, 拿到程序的call graph信息
- --sleep 60: 表示對進(jìn)程持續(xù)分析60s
2. 如何生成火焰圖
2.1 安裝火焰圖生成工具
Flame Graph工程實現(xiàn)了一套生成火焰圖的腳本, 直接clone下來使用
git clone https://github.com/brendangregg/FlameGraph.git
該文件夾下有很多perf語言腳本, 可完成不同堆棧分析

2.2 生成和創(chuàng)建火焰圖的步驟
捕獲堆棧: perf script -i perf.data &> perf.unfold
折疊堆棧: ./FlameGraph/FlameGraph/stackcollapse-perf.pl perf.unfold &> perf.folded
生成火焰圖: ./FlameGraph/FlameGraph/flamegraph.pl perf.folded > perf.svg
各個步驟的含義:
- 捕獲堆棧: 可以使用 perf、systemtap、dtrace 等工具抓取程序的運(yùn)行堆棧
- 折疊堆棧: 對捕獲的堆棧信息進(jìn)行分析組合, 將重復(fù)的堆棧累計在一起, 從而體現(xiàn)出負(fù)載和關(guān)鍵路徑, 由FlameGraph的stackcollapse程序生成, 注意程序路徑
- 生成火焰圖: 分析由stackcollapse輸出的堆棧信息的火焰圖, 執(zhí)行完后生成.svg圖片

2.3 火焰圖的含義
y軸表示調(diào)用棧,每一層都是一個函數(shù)。調(diào)用棧越深,火焰就越高,頂部就是正在執(zhí)行的函數(shù),下方都是它的父函數(shù)
x軸表示抽樣數(shù),如果一個函數(shù)在x軸占據(jù)的寬度越寬,就表示它被抽到的次數(shù)多,即執(zhí)行的時間占比越大。注意,x軸不代表時間,而是所有的調(diào)用棧合并后,按字母順序排列的
顏色無特殊含義, 因為火焰圖表示CPU的繁忙程度, 所以一般選擇暖色調(diào)
火焰圖就是看頂層的哪個函數(shù)占據(jù)的寬度最大。只要有"平頂",就表示該函數(shù)可能存在性能問題
鼠標(biāo)懸浮: (瀏覽器打開.svg圖片)可顯示函數(shù)名, 抽樣抽中的次數(shù), 占總抽樣次數(shù)的百分比

點(diǎn)擊放大: 點(diǎn)擊某一層,該層會占據(jù)所有寬度,顯示詳細(xì)信息,再點(diǎn)擊左上角ResetZoom可恢復(fù)

查找: Ctrl + F, 高亮顯示查找的函數(shù)

火焰圖的缺陷: 調(diào)用??赡懿煌暾? 當(dāng)調(diào)用棧過深時,某些系統(tǒng)只返回前面的一部分(比如前10層); 函數(shù)名可能缺失, 有些函數(shù)沒有名字,編譯器只用內(nèi)存地址來表示(比如匿名函數(shù)), 有可能是編譯器優(yōu)化等級過高
FlameGraph我們習(xí)慣稱之為"CPU火焰圖", 還有"瀏覽器火焰圖"(x軸是任務(wù)時間軸), “紅/藍(lán)差分火焰圖”, 紅藍(lán)差分火焰圖可以用來對比分析兩次修改的性能差異, 紅色表示上升, 藍(lán)色表示下降, 由此來尋找根因; 此外還有"Memory Flame Graphs"(檢測內(nèi)存占用量增加的原因), “Off-CPU Flame Graphs”(不在CPU上運(yùn)行的時間,如I/O時間等), “Hot/Cold Flame Graphs”(CPU和非CPU結(jié)合,顯示所有線程的運(yùn)行時間)
2.4 生成"紅/藍(lán)差分火焰圖"示例
修改源程序
#include <iostream>
using namespace std;
void delay()
{
int i,j;
for(i = 0; i < 1000000; i++)
j=i;
}
void function_1()
{
int i;
for(i=0 ; i < 20; i++)
delay();
}
void function_2()
{
int i;
for(i = 0; i< 20; i++)
delay();
}
int main(void)
{
std::cout << "begin: " << std::endl;
function_1();
function_2();
std::cout << "end!" << std::endl;
}
重新編譯執(zhí)行
g++ main.cpp -o main sudo perf record -g ./main # 生成新的perf.data
折疊堆棧
perf script -i perf.data &> perf.unfold # 生成新的perf.unfold ./FlameGraph/FlameGraph/stackcollapse-perf.pl perf.unfold &> perf.folded1
生成火焰圖
./FlameGraph/FlameGraph/flamegraph.pl perf.folded1 > perf2.svg
以perf.folded為基準(zhǔn),生成差分火焰圖
./FlameGraph/FlameGraph/difffolded.pl perf.folded perf.folded1 | ./FlameGraph/FlameGraph/flamegraph.pl > diff.svg
瀏覽器打開diff.svg

紅色部分表示function_1中delay耗時增加了, 藍(lán)色部分表示function_2中delay耗時減少了, 和我們修改的預(yù)期是一樣的
3. 使用perf分析節(jié)點(diǎn)CPU占比
執(zhí)行報錯1:sudo perf record -g ./可執(zhí)行文件, 執(zhí)行失敗。節(jié)點(diǎn)編譯完成后報錯找不到
error while loading shared libraries: liblibstatistics_collector.so

解決方法:搜索發(fā)現(xiàn)liblibstatistics_collector.so存在, 但通過export添加路徑后不生效
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/so_path 執(zhí)行后不管用
- sudo ldconfig # 動態(tài)鏈接庫管理, 讓不同目錄下的動態(tài)鏈接庫為系統(tǒng)所共享
- 或者試下 ldconfig 然后 perf record -g ./可執(zhí)行文件, 不要加sudo
- 執(zhí)行后生效
執(zhí)行報錯2:上一步生成的perf.data執(zhí)行perf report提示文件size field is 0
data size field is 0 which is unexpected

原因分析:看下來是perf record -g ./可執(zhí)行文件的形式?jīng)]有正確生成perf.data, 單獨(dú)執(zhí)行perf record進(jìn)行采樣
top # 查看程序PID = 228 perf record -p 228 -g # 生成perf.data, Ctrl + C結(jié)束錄制 perf report # 可正常讀取

生成火焰圖
perf script -i perf.data &> perf.unfold # 捕獲堆棧 ./FlameGraph/FlameGraph/stackcollapse-perf.pl perf.unfold &> perf.folded # 折疊堆棧 ./FlameGraph/FlameGraph/flamegraph.pl perf.folded > perf.svg # 生成火焰圖
瀏覽器打開.svg圖片

ros2的CPU占用,播包5min

ros1的CPU占用,播包5min
對比結(jié)論:
- 節(jié)點(diǎn)總體CPU占用在102%
- 長時播包測試可知,節(jié)點(diǎn)的CPU占用主要來自std::thread::State_impl占74.51%,其中主程序25%+多線程相關(guān)45%
- 多線程相關(guān)的45%分析
- 對比ros1的CPU占用,在ros2中節(jié)點(diǎn)的CPU占用高只是運(yùn)行機(jī)制的差異
- 對多線程管理占用的45%的CPU,包含除主程序外的多個任務(wù):不同topic消息隊列同步訪問,消息轉(zhuǎn)proto,消息收發(fā)同步;線程同步統(tǒng)計節(jié)點(diǎn)掉線信息;線程同步維護(hù)節(jié)點(diǎn)狀態(tài)信息等
- 此外,在添加多線程同步前,這部分的CPU還是1-2核占滿,線程間阻塞同步的方式降低了一個核以上的CPU占用,但線程同步還存在一部分的CPU占用
以上就是Linux使用perf分析CPU占用情況的方法步驟的詳細(xì)內(nèi)容,更多關(guān)于Linux perf分析CPU的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
linux如何mount掛載磁盤并設(shè)置開機(jī)自動mount的實現(xiàn)
這篇文章主要介紹了linux如何mount掛載磁盤并設(shè)置開機(jī)自動mount的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Linux進(jìn)程的優(yōu)先級&&進(jìn)程切換方式
本文概述進(jìn)程優(yōu)先級與調(diào)度算法,涵蓋優(yōu)先級調(diào)整方法(nice、renice命令)及Linux 2.6 O(1)調(diào)度器,通過運(yùn)行隊列、task_struct結(jié)構(gòu)和位圖優(yōu)化進(jìn)程調(diào)度效率2025-07-07
Linux使用 iftop 實時監(jiān)控網(wǎng)卡的流量
iftop可以用來監(jiān)控網(wǎng)卡的實時流量(可以指定網(wǎng)段)、反向解析IP、顯示端口信息等。這篇文章主要介紹了Linux 實時網(wǎng)卡流量監(jiān)控,需要的朋友可以參考下2019-11-11
Linux系統(tǒng)的SSL/TLS證書機(jī)制詳解
文章概述了SSL/TLS證書原理、Linux系統(tǒng)預(yù)裝證書的存儲與用途,以及新服務(wù)(如POP3)自動生成自簽名證書的過程和局限性,最后推薦使用Let's Encrypt等自動化工具提升安全性2025-09-09
CentOS 7 中firewall-cmd命令詳細(xì)介紹
這篇文章主要介紹了 CentOS 7 中firewall-cmd命令詳細(xì)介紹的相關(guān)資料,這里對CentOS 7的firewall-cmd命令一一介紹,希望能幫助開始使用的朋友,需要的朋友可以參考下2016-11-11
Linux系統(tǒng)下的重啟,關(guān)機(jī)命令以及reboot掛死問題解決方案
本文介紹了Linux系統(tǒng)中關(guān)機(jī)和重啟的命令及其作用,以及系統(tǒng)運(yùn)行等級的差別,此外,還分享了一個解決reboot關(guān)機(jī)卡死問題的方法2024-11-11

