牛逼的Linux性能剖析—perf


點(diǎn)擊「閱讀原文」查看良許原創(chuàng)精品視頻。
點(diǎn)擊「閱讀原文」查看良許原創(chuàng)精品視頻。
系統(tǒng)級(jí)性能優(yōu)化通常包括兩個(gè)階段:性能剖析(performance profiling)和代碼優(yōu)化。性能剖析的目標(biāo)是尋找性能瓶頸,查找引發(fā)性能問題的原因及熱點(diǎn)代碼。代碼優(yōu)化的目標(biāo)是針對(duì)具體性能問題而優(yōu)化代碼或編譯選項(xiàng),以改善軟件性能。本篇主要講性能分析中常用的工具——perf。
perf是一款Linux性能分析工具。Linux性能計(jì)數(shù)器是一個(gè)新的基于內(nèi)核的子系統(tǒng),它提供一個(gè)性能分析框架,比如硬件(CPU、PMU(Performance Monitoring Unit))功能和軟件(軟件計(jì)數(shù)器、tracepoint)功能。通過perf,應(yīng)用程序可以利用PMU、tracepoint和內(nèi)核中的計(jì)數(shù)器來(lái)進(jìn)行性能統(tǒng)計(jì)。它不但可以分析制定應(yīng)用程序的性能問題(per thread),也可以用來(lái)分析內(nèi)核的性能問題。
總之perf是一款很牛逼的綜合性分析工具,大到系統(tǒng)全局性性能,再小到進(jìn)程線程級(jí)別,甚至到函數(shù)及匯編級(jí)別。
調(diào)優(yōu)方向
可以從以下三種事件為調(diào)優(yōu)方向:
Hardware Event由PMU部件產(chǎn)生,在特定的條件下探測(cè)性能事件是否發(fā)生以及發(fā)生的次數(shù)。比如cache命中。
Software Event是內(nèi)核產(chǎn)生的事件,分布在各個(gè)功能模塊中,統(tǒng)計(jì)和操作系統(tǒng)相關(guān)性能事件。比如進(jìn)程切換,tick數(shù)等。
Tracepoint Event是內(nèi)核中靜態(tài)tracepoint所觸發(fā)的事件,這些tracepoint用來(lái)判斷程序運(yùn)行期間內(nèi)核的行為細(xì)節(jié)(這些tracepint的對(duì)應(yīng)的sysfs節(jié)點(diǎn)在/sys/kernel/debug/tracing/events目錄下)。比如slab分配器的分配次數(shù)等。
perf 的使用
| 序號(hào) | 命令 | 作用 |
| 1 | annotate | 解析perf record生成的perf.data文件,顯示被注釋的代碼。 |
| 2 | archive | 根據(jù)數(shù)據(jù)文件記錄的build-id,將所有被采樣到的elf文件打包。利用此壓縮包,可以再任何機(jī)器上分析數(shù)據(jù)文件中記錄的采樣數(shù)據(jù)。 |
| 3 | bench | perf中內(nèi)置的benchmark,目前包括兩套針對(duì)調(diào)度器和內(nèi)存管理子系統(tǒng)的benchmark。 |
| 4 | buildid-cache | 管理perf的buildid緩存,每個(gè)elf文件都有一個(gè)獨(dú)一無(wú)二的buildid。buildid被perf用來(lái)關(guān)聯(lián)性能數(shù)據(jù)與elf文件。 |
| 5 | buildid-list | 列出數(shù)據(jù)文件中記錄的所有buildid。 |
| 6 | diff | 對(duì)比兩個(gè)數(shù)據(jù)文件的差異。能夠給出每個(gè)符號(hào)(函數(shù))在熱點(diǎn)分析上的具體差異。 |
| 7 | evlist | 列出數(shù)據(jù)文件perf.data中所有性能事件。 |
| 8 | inject | 該工具讀取perf record工具記錄的事件流,并將其定向到標(biāo)準(zhǔn)輸出。在被分析代碼中的任何一點(diǎn),都可以向事件流中注入其它事件。 |
| 9 | kmem | 針對(duì)內(nèi)核內(nèi)存(slab)子系統(tǒng)進(jìn)行追蹤測(cè)量的工具 |
| 10 | kvm | 用來(lái)追蹤測(cè)試運(yùn)行在KVM虛擬機(jī)上的Guest OS。 |
| 11 | list | 列出當(dāng)前系統(tǒng)支持的所有性能事件。包括硬件性能事件、軟件性能事件以及檢查點(diǎn)。 |
| 12 | lock | 分析內(nèi)核中的鎖信息,包括鎖的爭(zhēng)用情況,等待延遲等。 |
| 13 | mem | 內(nèi)存存取情況 |
| 14 | record | 收集采樣信息,并將其記錄在數(shù)據(jù)文件中。隨后可通過其它工具對(duì)數(shù)據(jù)文件進(jìn)行分析。 |
| 15 | report | 讀取perf record創(chuàng)建的數(shù)據(jù)文件,并給出熱點(diǎn)分析結(jié)果。 |
| 16 | sched | 針對(duì)調(diào)度器子系統(tǒng)的分析工具。 |
| 17 | script | 執(zhí)行perl或python寫的功能擴(kuò)展腳本、生成腳本框架、讀取數(shù)據(jù)文件中的數(shù)據(jù)信息等。 |
| 18 | stat | 執(zhí)行某個(gè)命令,收集特定進(jìn)程的性能概況,包括CPI、Cache丟失率等。 |
| 19 | test | perf對(duì)當(dāng)前軟硬件平臺(tái)進(jìn)行健全性測(cè)試,可用此工具測(cè)試當(dāng)前的軟硬件平臺(tái)是否能支持perf的所有功能。 |
| 20 | timechart | 針對(duì)測(cè)試期間系統(tǒng)行為進(jìn)行可視化的工具 |
| 21 | top | 類似于linux的top命令,對(duì)系統(tǒng)性能進(jìn)行實(shí)時(shí)分析。 |
| 22 | trace | 關(guān)于syscall的工具。 |
| 23 | probe | 用于定義動(dòng)態(tài)檢查點(diǎn)。 |
全局性概況:
perf list查看當(dāng)前系統(tǒng)支持的性能事件;
perf bench對(duì)系統(tǒng)性能進(jìn)行摸底;
perf test對(duì)系統(tǒng)進(jìn)行健全性測(cè)試;
perf stat對(duì)全局性能進(jìn)行統(tǒng)計(jì);
全局細(xì)節(jié):
perf top可以實(shí)時(shí)查看當(dāng)前系統(tǒng)進(jìn)程函數(shù)占用率情況;
perf probe可以自定義動(dòng)態(tài)事件;
特定功能分析:
perf kmem針對(duì)slab子系統(tǒng)性能分析;
perf kvm針對(duì)kvm虛擬化分析;
perf lock分析鎖性能;
perf mem分析內(nèi)存slab性能;
perf sched分析內(nèi)核調(diào)度器性能;
perf trace記錄系統(tǒng)調(diào)用軌跡;
最常用功能perf record,可以系統(tǒng)全局,也可以具體到某個(gè)進(jìn)程,更甚具體到某一進(jìn)程某一事件;可宏觀,也可以很微觀。
pref record記錄信息到perf.data;
perf report生成報(bào)告;
perf diff對(duì)兩個(gè)記錄進(jìn)行diff;
perf evlist列出記錄的性能事件;
perf annotate顯示perf.data函數(shù)代碼;
perf archive將相關(guān)符號(hào)打包,方便在其它機(jī)器進(jìn)行分析;
perf script將perf.data輸出可讀性文本;
可視化工具perf timechart
perf timechart record記錄事件;
perf timechart生成output.svg文檔;
火焰圖
火焰圖(Flame Graph)是由Linux性能優(yōu)化大師Brendan Gregg發(fā)明的,和所有其他的trace和profiling方法不同的是,F(xiàn)lame Graph以一個(gè)全局的視野來(lái)看待時(shí)間分布,它從底部往頂部,列出所有可能的調(diào)用棧。其他的呈現(xiàn)方法,一般只能列出單一的調(diào)用?;蛘叻菍哟位臅r(shí)間分布。
以典型的分析CPU時(shí)間花費(fèi)到哪個(gè)函數(shù)的on-cpu火焰圖為例來(lái)展開。CPU火焰圖中的每一個(gè)方框是一個(gè)函數(shù),方框的長(zhǎng)度,代表了它的執(zhí)行時(shí)間,所以越寬的函數(shù),執(zhí)行越久?;鹧鎴D的樓層每高一層,就是更深一級(jí)的函數(shù)被調(diào)用,最頂層的函數(shù),是葉子函數(shù)。

火焰圖的生成過程是:?
先trace系統(tǒng),獲取系統(tǒng)的profiling數(shù)據(jù)?
用腳本來(lái)繪制
腳本獲?。?span style="font-size: 12px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;line-height: 19.2px;widows: 1;background-color: rgb(255, 255, 255);">git?clone https://github.com/brendangregg/FlameGraph
下面通過實(shí)例來(lái)體驗(yàn)以下火焰圖的生成過程:
#include?
func_d()
{
????int?i;
????for(i=0;i<50000;i++);
}
func_a()
{
????int?i;
????for(i=0;i<100000;i++);
????func_d();
}
func_b()
{
????int?i;
????for(i=0;i<200000;i++);
}
func_c()
{
????int?i;
????for(i=0;i<300000;i++);
}
void*?thread_fun(void*?param)
{
????while(1)?{
????????int?i;
????????for(i=0;i<100000;i++);
????????func_a();
????????func_b();
????????func_c();
????}
}
int?main(void)
{
????pthread_t?tid1,tid2;
????int?ret;
????ret=pthread_create(&tid1,NULL,thread_fun,NULL);
????if(ret==-1){
????????...
????}
????ret=pthread_create(&tid2,NULL,thread_fun,NULL);
????...
????if(pthread_join(tid1,NULL)!=0){
????????...
????}
????if(pthread_join(tid2,NULL)!=0){
????????...
????}
????return?0;
}先用類似perf top分析出來(lái)CPU時(shí)間主要花費(fèi)在哪里:
$ gcc test.c -pthread
$ ./a.out&
$ sudo perf top

perf top提示出來(lái)了fun_a()、fun_b()、fun_c(), fun_d(),thread_func()這些函數(shù)內(nèi)部的代碼是CPU消耗大戶,但是它缺乏一個(gè)全局的視野,我們無(wú)法看出全局的調(diào)用棧,也弄不清楚這些函數(shù)之間的關(guān)系。火焰圖則不然,我們用下面的命令可以生成火焰圖(以root權(quán)限運(yùn)行):
$ perf record -F 99 -a -g -- sleep 60
$ perf script | ./stackcollapse-perf.pl > out.perf-folded
$ ./flamegraph.pl out.perf-folded > perf-kernel.svg
上述程序捕獲系統(tǒng)的行為60秒鐘,最后調(diào)用flamegraph.pl生成一個(gè)火焰圖perf-kernel.svg,用看圖片的工具就可以打開這個(gè)svg。

上述火焰圖顯示出了a.out中,thread_func()、func_a()、func_b()、fun_c()和func_d()的時(shí)間分布。
從上述火焰圖可以看出,雖然thread_func()被兩個(gè)線程調(diào)用,但是由于thread_func()之前的調(diào)用棧是一樣的,所以2個(gè)線程的thread_func()調(diào)用是合并為同一個(gè)方框的。
除了on-cpu的火焰圖以外,off-cpu的火焰圖,對(duì)于分析系統(tǒng)堵在IO、SWAP、取得鎖方面的幫助很大,有利于分析系統(tǒng)在運(yùn)行的時(shí)候究竟在等待什么,系統(tǒng)資源之間的彼此伊伴。
比如,下面的火焰圖顯示,nginx的吞吐能力上不來(lái)的很多程度原因在于sem_wait()等待信號(hào)量。
關(guān)于火焰圖的更多細(xì)節(jié)和更多種火焰圖各自的功能,可以訪問:?
http://www.brendangregg.com/flamegraphs.html
推薦閱讀:
這能忍?阿里、騰訊、京東、百度聯(lián)合出手了?。?/span>
5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹莓派,等等。在公眾號(hào)內(nèi)回復(fù)「1024」,即可免費(fèi)獲?。。?/span>
