天天看點

宋寶華:火焰圖 全局視野的 Linux 性能剖析

作者簡介:宋寶華,他有10幾年的Linux開發經驗。他長期在大型企業擔任一線工程師和系統架構師,編寫大量的Linux代碼,并負責在gerrit上review其他同僚的代碼。Barry Song是Linux的活躍開發者,是某些核心版本的最活躍開發者之一(如https://lwn.net/Articles/395961/ 、https://lwn.net/Articles/429912/ ),也曾是一ARM SoC系列在Linux mainline的maintainer。 他也是china-pub等據銷售評估的2008年度“十大暢銷經典”,“十佳原創精品”圖書《Linux裝置驅動開發詳解》的作者和《Essential Linux Device Driver》的譯者。同時書寫了很多技術文章,是51CTO 2012年度“十大傑出IT部落格”得主及51CTO、CSDN的專家部落客。他也熱衷于開源項目,正在開發LEP(Linux Easy Profiling,http://www.linuxep.com )項目,并希望獲得更多人的參與和幫助。

火焰圖(Flame Graph)是由Linux性能優化大師Brendan Gregg發明的,和所有其他的trace和profiling方法不同的是,Flame Graph以一個全局的視野來看待時間分布,它從底部往頂部,列出所有可能的調用棧。其他的呈現方法,一般隻能列出單一的調用棧或者非階層化的時間分布。

我最快樂的童年時代,每逢冬天,尤其是春節的時候,和一家人圍坐在火堆旁邊烤火。這已經成為最美好的回憶,其實人生追求的快樂非常簡單。火焰圖的火焰首先來自于根,然後以火苗的形式往上面竄。可以把從靠近地面的根到頂上的每個火苗,想想成一個調用棧。由于火苗有很多根,這正好也和現實生活中程式的執行邏輯相似。

宋寶華:火焰圖 全局視野的 Linux 性能剖析

以典型的分析CPU時間花費到哪個函數的on-cpu火焰圖為例來展開。

CPU火焰圖中的每一個方框是一個函數,方框的長度,代表了它的執行時間,是以越寬的函數,執行越久。火焰圖的樓層每高一層,就是更深一級的函數被調用,最頂層的函數,是葉子函數。

宋寶華:火焰圖 全局視野的 Linux 性能剖析

火焰圖的生成過程是:

先trace系統,擷取系統的profiling資料

用腳本來繪制

系統的profiling資料擷取,可以選擇最流行的perf record,而後把采集的資料進行加工處理,繪制為火焰圖。其中第二步的繪制火焰圖的腳本程式,通過如下方式擷取:

廢話不多說,直接從最簡單的例子開始說起。talk is cheap, show you the cde,代碼如下:

則這三個函數,在火焰圖中呈現的樣子為:

宋寶華:火焰圖 全局視野的 Linux 性能剖析

a()的2/3的時間花在b()上面,而b()的1/3的時間花在c()上面。很多個這樣的a->b->c的火苗堆在一起,就構成了火焰圖。

宋寶華:火焰圖 全局視野的 Linux 性能剖析

進一步了解火焰圖的最好方法仍然是通過一個實際的案例,下面的程式建立2個線程,兩個線程的handler都是thread_fun(),之後thread_fun()調用fun_a()、fun_b()、fun_c(),而fun_a()又會調用fun_d():

先看看不用火焰圖的缺點在哪裡。

如果不用火焰圖,我們也可以用類似perf top這樣的工具分析出來CPU時間主要花費在哪裡了:

perf top的顯示結果如下:

宋寶華:火焰圖 全局視野的 Linux 性能剖析

perf top提示出來了fun_a()、fun_b()、fun_c(), fun_d(),thread_func()這些函數内部的代碼是CPU消耗大戶,但是它缺乏一個全局的視野,我們無法看出全局的調用棧,也弄不清楚這些函數之間的關系。火焰圖則不然,我們用下面的指令可以生成火焰圖(以root權限運作):

上述程式捕獲系統的行為60秒鐘,最後調用flamegraph.pl生成一個火焰圖perf-kernel.svg,用看圖檔的工具就可以打開這個svg。

宋寶華:火焰圖 全局視野的 Linux 性能剖析

上述火焰圖顯示出了a.out中,thread_func()、func_a()、func_b()、fun_c()和func_d()的時間分布。

從上述火焰圖可以看出,雖然thread_func()被兩個線程調用,但是由于thread_func()之前的調用棧是一樣的,是以2個線程的thread_func()調用是合并為同一個方框的。

除了on-cpu的火焰圖以外,off-cpu的火焰圖,對于分析系統堵在IO、SWAP、取得鎖方面的幫助很大,有利于分析系統在運作的時候究竟在等待什麼,系統資源之間的彼此伊伴。

比如,下面的火焰圖顯示,nginx的吞吐能力上不來的很多程度原因在于sem_wait()等待信号量。

宋寶華:火焰圖 全局視野的 Linux 性能剖析

上圖摘自Yichun Zhang (agentzh)的《Introduction to offCPU Time Flame Graphs》。

關于火焰圖的更多細節和更多種火焰圖各自的功能,可以通路:

http://www.brendangregg.com/flamegraphs.html

本文來自 Linuxerr 微信公衆号

繼續閱讀