Linux下性能分析工具Perf安裝與用法
1、Perf介紹
perf是Linux下的一款性能分析工具,能夠進(jìn)行函數(shù)級(jí)與指令級(jí)的熱點(diǎn)查找。它由一個(gè)叫“Performance counters“的內(nèi)核子系統(tǒng)實(shí)現(xiàn),基于事件采樣原理,以性能事件為基礎(chǔ),支持針對(duì)處理器相關(guān)性能指標(biāo)與操作系統(tǒng)相關(guān)性能指標(biāo)的性能剖析,可用于性能瓶頸的查找與熱點(diǎn)代碼的定位。
Perf的主要功能和用途如下:
事件采樣:Perf使用硬件性能計(jì)數(shù)器來采樣事件,如CPU指令、緩存命中、緩存失效等,從而獲取系統(tǒng)在運(yùn)行時(shí)的性能數(shù)據(jù)。
調(diào)用圖:Perf可以生成函數(shù)調(diào)用圖,顯示函數(shù)之間的調(diào)用關(guān)系和耗時(shí),幫助識(shí)別程序的熱點(diǎn)和性能瓶頸。
火焰圖:火焰圖是Perf輸出的一種可視化圖表,它可以直觀地展示函數(shù)調(diào)用的耗時(shí)情況和函數(shù)的調(diào)用關(guān)系,以便快速準(zhǔn)確地識(shí)別最頻繁的代碼路徑,幫助快速定位性能瓶頸。
內(nèi)存分析:Perf可以收集內(nèi)存事件,如內(nèi)存訪問、缺頁異常等,幫助識(shí)別內(nèi)存性能問題。
鎖分析:Perf可以監(jiān)測鎖的使用情況,幫助發(fā)現(xiàn)多線程程序中的競爭問題。
Tracing支持:Perf支持Linux Trace Toolkit Next Generation (LTTng)和eBPF等跟蹤工具,用于深入分析系統(tǒng)的行為。
報(bào)告生成:Perf能夠生成詳細(xì)的報(bào)告和統(tǒng)計(jì)信息,方便用戶理解和分析性能數(shù)據(jù)。
2、火焰圖分類
(1)CPU
用途:檢測導(dǎo)致CPU運(yùn)行繁忙的原因。
(2)Memory Flame Graphs
用途:檢測應(yīng)用程序內(nèi)存使用量增加的原因。
(3)Off-CPU Flame Graphs
用途:有些性能問題不是CPU的性能問題,即進(jìn)程和線程不在CPU上運(yùn)行時(shí)花費(fèi)角度的時(shí)間,而是在程序請(qǐng)求期間花費(fèi)了不少時(shí)間,這種情況也會(huì)成比例的影響性能。
(4)Hot/Cold Flame Graphs
用途:將CPU和非CPU火焰圖結(jié)合在一起。它在一個(gè)圖表中顯示了所有線程的運(yùn)行時(shí)間,并允許直接比較在CPU和非CPU上的代碼路徑持續(xù)時(shí)間。
(5)Differential
用途:紅藍(lán)差異火焰圖,分析不同時(shí)刻CPU性能變化的原因。
3、火焰圖安裝命令
(1)安裝Perf工具
$ sudo apt-get install linux-tools-$(uname -r) linux-tools-generic -y //下載Perf $ perf -v //查看安裝Perf的版本
(2)下載可視化工具FlameGraph
下載地址:GitHub - brendangregg/FlameGraph: Stack trace visualizer
4、火焰圖demo測試
測試程序如下:
#include <stdio.h> #define DEF_PRINT void funcA() { for(int i=0; i < 10*10000;i++) { #ifdef DEF_PRINT printf("funcA\n"); #endif } } void funcB() { for(int i=0; i < 20*10000;i++) { #ifdef DEF_PRINT printf("funcB\n"); #endif } } void funcC() { for(int i=0; i < 30*10000;i++) { #ifdef DEF_PRINT printf("funcC\n"); #endif } } void printf1(); void printf2(); void funcD() { for(int i=0; i < 20*10000;i++) { #ifdef DEF_PRINT printf("funcD\n"); #endif } printf1(); } void printf1() { for(int i=0; i < 10*10000;i++) { #ifdef DEF_PRINT printf("printf1\n"); #endif } printf2(); } void printf2() { for(int i=0; i < 10*10000;i++) { #ifdef DEF_PRINT printf("printf2\n"); #endif } } int main() { while (true) { funcA(); funcB(); funcC(); funcD(); } return 0; }
程序編譯命令:
g++ -g -O0 main.cpp -o main //-g帶調(diào)試信息編譯,禁止優(yōu)化O0,
(1)生成CPU火焰圖1
生成火焰圖步驟如下:
程序運(yùn)行結(jié)果如下:
//上面main程序運(yùn)行時(shí),使用top查看,進(jìn)程PID為5606,CPU為86.3%左右。 $ sudo perf record -F 99 -p 5606 -g -- sleep 30 //-F 99 表示每秒99次采樣, -p 5606 是進(jìn)程號(hào), 即對(duì)哪個(gè)進(jìn)程進(jìn)行分析, -g 表示記錄調(diào)用棧, sleep 30 則是持續(xù)30秒。 $ sudo perf script -i perf.data &>perf.unfold //perf script 工具對(duì) perf.data 進(jìn)行解析,生成折疊后的調(diào)用棧。 $ ../FlameGraph/stackcollapse-perf.pl perf.unfold &>perf.folded //下載的可視化工具FlameGraph在當(dāng)前文件上一層,用 stackcollapse-perf.pl 將 perf 解析出的內(nèi)容 perf.unfold 中的符號(hào)進(jìn)行折疊。 $ ../FlameGraph/flamegraph.pl perf.folded >perf1.svg //生成svg圖
使用瀏覽器打開perf.svg圖,效果如下:
(2)火焰圖表解析
上圖中每個(gè)方塊代表堆棧中的一個(gè)函數(shù),也叫堆棧幀。
y軸:表示堆棧深度,火焰越高,表示函數(shù)調(diào)用層級(jí)越深,最頂部的方塊表示當(dāng)前CPU上運(yùn)行的函數(shù),每一塊的函數(shù)下方都是當(dāng)前函數(shù)的調(diào)用方。
x軸:表示當(dāng)前函數(shù)的采樣數(shù),與大多數(shù)圖表不同,它不顯示從左到右的時(shí)間流逝。左到右的排序沒有意義(它按字母順序排序以最大程度地合并幀),方框的寬度顯示了它在CPU上運(yùn)行的總時(shí)間(基于采樣計(jì)數(shù))。哪個(gè)方塊的寬度比較大,就表示該函數(shù)可能存在性能問題。
注意:圖標(biāo)中顏色不具有顯著意義,通常是隨機(jī)選擇的暖色調(diào)。這種可視化稱為"火焰圖",因?yàn)樗畛跤糜陲@示CPU上的熱點(diǎn),而且看起來像火焰。
它也是交互式的:將鼠標(biāo)懸停在SVG上以顯示詳細(xì)信息,并單擊進(jìn)行縮放。
(3)當(dāng)前程序圖標(biāo)分析
從(1)中火焰圖中看出,沒有demo中定義的函數(shù),這是因?yàn)閜rintf函數(shù)占用改進(jìn)程的CPU性能較高,而for循環(huán)邏輯占用性能較低,可以點(diǎn)擊火焰圖上的搜索按鍵Search進(jìn)行搜索,本文搜索程序入口函數(shù)。
確定入口函數(shù)的步驟如下:
a> 入口函數(shù)地址確定
輸入下面命令
$ readelf -h main
可執(zhí)行文件信息如下:
b> 獲取對(duì)應(yīng)地址入口函數(shù)
輸入下面命令:
$ readelf -s main
由上圖可知入口函數(shù)為_start,所以搜索_start函數(shù)。
_start搜索結(jié)果如下:
點(diǎn)擊__libc_start_main函數(shù),進(jìn)入對(duì)于函數(shù)調(diào)用過程,如下:
(4)生成火焰圖2
將上面的代碼中的#define DEF_PRINT 行進(jìn)行屏蔽,這樣函數(shù)就不會(huì)打印輸出到屏幕上。重新編譯代碼,運(yùn)行。
生成火焰圖步驟跟上面(1)中一樣,只是-p參數(shù)的進(jìn)程ID號(hào)不同,生成的svg圖片如下:
由svg圖表可知,funcA在mainNoPrint進(jìn)程中,占用該進(jìn)程CPU 10%,funcB占用該進(jìn)程CPU 20%,funcC占用該進(jìn)程CPU 30%,funcD占用該進(jìn)程CPU 40%。
(5)生成差分火焰圖
運(yùn)行mainNoPrint函數(shù),抓取系統(tǒng)所有進(jìn)程的CPU,命令如下:
$ sudo perf record -F 99 -a -g -- sleep 30 //a表示對(duì)所有進(jìn)程堆棧數(shù)據(jù)進(jìn)行抓取 $ sudo perf script -i perf.data &>perf.unfold $ ../FlameGraph/stackcollapse-perf.pl perf.unfold &>perf.folded1 $ ../FlameGraph/flamegraph.pl perf.folded1 >perf1.svg
生成的火焰圖如下:
停止mainNoPrint程序,抓取系統(tǒng)所有進(jìn)程的CPU,命令如下:
$ sudo perf record -F 99 -a -g -- sleep 30 $ sudo perf script -i perf.data &>perf.unfold $ ../FlameGraph/stackcollapse-perf.pl perf.unfold &>perf.folded2 $ ../FlameGraph/flamegraph.pl perf.folded2 >perf2.svg
生成的火焰圖如下:
以perf.folded2的為基準(zhǔn),生成差分火焰圖,命令如下:
$./FlameGraph/difffolded.pl perf.folded2 perf.folded1|../FlameGraph/flamegraph.pl >diff1.svg
生成的差分火焰圖如下:
由紅色部分圖可知,CPU中funcD等函數(shù)占用的CPU增加了,藍(lán)色部分相對(duì)于上次CPU減少了。
以上就是Linux下性能分析工具Perf安裝與用法的詳細(xì)內(nèi)容,更多關(guān)于Linux Perf安裝與使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
linux?類型??版本?內(nèi)存?磁盤?查詢命令介紹
這篇文章介紹了linux?類型?、版本、內(nèi)存、磁盤?查詢命令,希望本篇文章可以幫助到大家的學(xué)習(xí),喜歡本篇文章可以收藏一下方便下次瀏覽2021-11-11ubuntu系統(tǒng)中/etc/rc.local和/etc/init.d/rc.local的區(qū)別詳解
這篇文章主要給大家介紹了關(guān)于在ubuntu系統(tǒng)下/etc/rc.local和/etc/init.d/rc.local區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)需要的朋友們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-08-08Linux systemV消息隊(duì)列和信號(hào)量詳解
這篇文章主要介紹了Linux systemV消息隊(duì)列和信號(hào)量,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03