Perf工具可用來(lái)對(duì)軟件進(jìn)行優(yōu)化,包括算法優(yōu)化(空間復(fù)雜度、時(shí)間復(fù)雜度)和代碼優(yōu)化(提高執(zhí)行速度、減少內(nèi)存占用)等等,perf 最常用的參數(shù)有top、stat、record,另外還有l(wèi)ist和report等。
本文主要使用Perf的record,script以及FlameGraph工具生成火焰圖,來(lái)進(jìn)一步分析性能瓶頸和函數(shù)調(diào)用。
一、生成采樣數(shù)據(jù)perf.data
使用perf record 采集數(shù)據(jù),其中-g表示記錄調(diào)用棧,-p 49383是進(jìn)程號(hào),即對(duì)哪個(gè)進(jìn)程進(jìn)行分析。采集后可以ctrl+c終止。
-e參數(shù)來(lái)統(tǒng)計(jì)需要關(guān)注的事件。 多個(gè)事件就用多個(gè)-e 連接。此處我?guī)Я薱pu-clock,cpu-clock可以用來(lái)表示程序執(zhí)行經(jīng)過的真實(shí)時(shí)間,而無(wú)論CPU處于什么狀態(tài)(Pn(n非0)或者是C狀態(tài))。
除了cpu-clock事件,比較常用的還有CPU cycle,CPU cycles用來(lái)表示執(zhí)行程序指令花費(fèi)的時(shí)鐘周期數(shù),如果CPU處于Pn(n非0)或者是C狀態(tài),則cycles的產(chǎn)生速度會(huì)減慢。
如果想查看哪些代碼消耗的真實(shí)時(shí)間多,則可以使用cpu-clock事件;而如果想查看哪些代碼消耗的時(shí)鐘周期多,則可以使用CPU cycles事件。
除了此類cpu火焰圖,也可以帶上其他類型的事件進(jìn)行統(tǒng)計(jì),例如內(nèi)存火焰圖,分析內(nèi)存的變化情況,可以進(jìn)一步幫助分析內(nèi)存被哪些模塊占用、內(nèi)存泄露問題的原因等問題。bio火焰圖,統(tǒng)計(jì)io的耗時(shí)由哪些函數(shù)占用,便于分析優(yōu)化io性能。此處不做贅述。
perf record -e cpu-clock -g -p 49383
除此之外,常見的還可以帶上如下選項(xiàng):
-F 99:表示每秒99次
sleep 30:采集持續(xù)30秒,這樣就不需要手動(dòng)ctrl+c終止。
-o xxx:指定采集后輸出的文件名等。
-t:指定線程TID。
-a:顯示在所有CPU上的性能統(tǒng)計(jì)信息。
-C:顯示在指定CPU上的性能統(tǒng)計(jì)信息。

第一步生成的perf.data文件其實(shí)也可以用perf report查看,只不過不直觀
perf report -n --stdio -i perf.data

二、用perf script工具對(duì)perf.data進(jìn)行解析
-i跟第一步收集的文件,進(jìn)行解析
perf script -i perf.data > perf.script

三、將perf.script中的符號(hào)進(jìn)行折疊
使用FlameGraph的stackcollapse-perf.pl折疊調(diào)用棧
./stackcollapse-perf.pl perf.script > perf.folded

四、生成svg火焰圖
使用FlameGraph的flamegraph.pl生成svg格式的火焰圖
./flamegraph.pl perf.folded > perf.svg
五、查看火焰圖
生成的火焰圖大概是如下這樣

其中每一個(gè)方框是一個(gè)函數(shù),鼠標(biāo)懸浮時(shí)會(huì)顯示完整的函數(shù)名、抽樣抽中的次數(shù)、占據(jù)總抽樣次數(shù)的百分比。方框的長(zhǎng)度,代表了它的執(zhí)行時(shí)間,所以越寬的函數(shù),就表示它被抽到的次數(shù)多,即執(zhí)行的時(shí)間長(zhǎng)。調(diào)用棧越深,火焰就越高,頂部就是正在執(zhí)行的函數(shù),下方都是它的父函數(shù)。
可以看到all上邊的第一個(gè)就是postgres。如下的每個(gè)方框,即函數(shù)都可以點(diǎn)擊,點(diǎn)擊后,會(huì)顯示其對(duì)應(yīng)調(diào)用的子函數(shù)。例如點(diǎn)擊XLogInsertRecord函數(shù),可以顯示出其調(diào)用的堆棧

點(diǎn)擊hash_search_with_hash_value,顯示它調(diào)用的堆棧。

火焰圖主要看頂層的哪個(gè)函數(shù)占據(jù)的寬度最大。只要有"平頂"(plateaus),就表示該函數(shù)可能存在性能問題,可能是瓶頸。可以嘗試對(duì)此類函數(shù)占用時(shí)間長(zhǎng)的原因分析和優(yōu)化,從而提高性能。




