Java FlameGraph 火焰图
上周一個(gè)偶然的機(jī)會(huì)聽(tīng)同事提到了Java FlameGraph,剛實(shí)驗(yàn)了一下,效果非常好。
一、什么是FlameGraph
直接看圖說(shuō)話。FlameGraph 是 SVG格式,矢量圖,可以隨意擴(kuò)大縮小,看不清的信息可以放大看。圖中,各種紅橙黃色沒(méi)有什么意義,僅僅做區(qū)分用;x軸橫條寬度來(lái)度量時(shí)間指標(biāo),表明每個(gè)接口實(shí)際占用的CPU時(shí)間;y軸代表線程棧的層次,從最底下往上表示堆棧的層層調(diào)用。通過(guò)看圖,可以發(fā)現(xiàn)哪個(gè)接口占用的CPU時(shí)間較多,從而優(yōu)化;同時(shí),可以發(fā)現(xiàn)調(diào)用關(guān)系。
?
Java火焰圖的作者是Brendan Gregg,他的博客非常有意思,很多關(guān)于性能的分析。以下鏈接是對(duì)每個(gè)類別的火焰圖的詳細(xì)說(shuō)明。
什么是Java Flame Graphs:Java Flame Graphs
On-CPU:CPU Flame Graphs
Off-CPU:Off-CPU Flame Graphs
Memory:Memory Leak (and Growth) Flame Graphs
Hot/Cold:Hot/Cold Flame Graphs
Differential:Differential Flame Graphs
關(guān)于火焰圖的PPT(講解得非常詳細(xì)):Blazing Performance with Flame Graphs
?
二、如何生成
兩個(gè)步驟:1. 需要java profiler生成trace文件? 2. 將trace文件轉(zhuǎn)換為svg格式的火焰圖文件。
1.?需要java profiler生成trace文件
在使用Profiler對(duì)CPU進(jìn)行采樣時(shí),根據(jù)CPU當(dāng)前執(zhí)行所處棧位置以及各個(gè)函數(shù)棧在總的采樣次數(shù)所占比例就可以得出各個(gè)函數(shù)執(zhí)行時(shí)的CPU占用比例。常用的是lightweight-java-profiler。還有其他的選擇,比如honest-profiler,lightweight-java-profiler會(huì)從java虛擬機(jī)啟動(dòng)開(kāi)始采樣,而有時(shí)候我們需要在CPU飆高的時(shí)候開(kāi)始,這時(shí)候honest-profiler提供的動(dòng)態(tài)啟停功能就有用武之地了。也有使用perf生成火焰圖。(*perf 要研究一下)
下面以lightweight-java-profiler 舉例
(1) 從github下載軟件
(2) 編譯 make all
(3) 生成的程序存放在build-64文件夾下面
(4)(可選)可以更改一些lightweight-java-profiler的一些選項(xiàng),打開(kāi)src/globals.h文件。在長(zhǎng)時(shí)間采樣時(shí),可以適當(dāng)?shù)販p少每秒采樣次數(shù),不然最終生成的文件會(huì)很大,分析起來(lái)比較麻煩。
// 每秒采樣頻率 static const int kNumInterrupts = 100; // Maximum number of stack traces線程棧個(gè)數(shù) static const int kMaxStackTraces = 3000; // 采樣棧深度 static const int kMaxFramesToCapture = 128;kNumInterrupts: 每秒鐘抽取樣本的次數(shù);
kMaxStackTraces: 線程棧的最大數(shù)量
kMaxFramesToCapture: 線程棧的深度
?
(5)運(yùn)行Java程序
java -agentpath:path/to/liblagent.so ......
(6)java程序啟動(dòng)后會(huì)在當(dāng)前目錄生成一個(gè)traces.txt文件,但文件中只有一些說(shuō)明信息。程序正常結(jié)束(不殺掉進(jìn)程)后,才會(huì)寫(xiě)入具體采樣信息。
?
2.將trace文件轉(zhuǎn)換為svg格式的火焰圖文件。
(1)從github下載FlameGraph
(2)轉(zhuǎn)換?
./stackcollapse-ljp.awk < traces.txt | ./flamegraph.pl > traces.svg (3)瀏覽器中打開(kāi)traces.svg文件 三、簡(jiǎn)單討論一下Java profiler 關(guān)于采樣工具的選取,可以看看文章 Evaluating the Accuracy of Java Profilers ,這里面列舉了xprof,hprof,jprofile和yourkit四種采樣器,并通過(guò)幾個(gè)壓測(cè)場(chǎng)景證明了這幾種采樣器的結(jié)果是相互矛盾的。總結(jié)的原因有兩點(diǎn): 1. 采樣器采樣點(diǎn)不夠隨機(jī),這幾種采樣器都只有在safe point采樣; 2. 不同的采樣器會(huì)注入不同的代碼,從而影響程序優(yōu)化過(guò)程,同時(shí)也影響了safe point的分布,進(jìn)一步造成采樣差異; honest-profiler號(hào)稱是避開(kāi)了通過(guò)SUN/Oracle management agent去采樣堆棧,而是使用自己實(shí)現(xiàn)的使用UNIX 操作系統(tǒng)信號(hào)和為Oracle Performance Studio 設(shè)計(jì)的內(nèi)部API的sampling agent,從而提升了采樣準(zhǔn)確率。 還有一篇文章和 Why many profilers have serous problems。 Java profiler 的兩個(gè)常見(jiàn)方式: 1.修改代碼,從而實(shí)現(xiàn)采樣。問(wèn)題是:1. 增加開(kāi)銷;2. 修改了你的代碼,導(dǎo)致java編譯器的優(yōu)化行為不確定;3. 影響了代碼的層次,層次越深自然也影響 執(zhí)行效率。 2.通過(guò)獲取on-cpu線程的線程棧方式。問(wèn)題是:獲取系統(tǒng)范圍的線程棧,jvm必須處于safepoint狀態(tài)(看文章What is Java safepoint)。只有當(dāng)線程處于safepoint狀態(tài)的時(shí)候,別的線程才能去獲取它的線程棧,而這個(gè)safepoint是由jvm 控制的,這對(duì)于profiler非常不利,有可能一個(gè)很熱的代碼塊,jvm不會(huì)在該代碼塊中間放置safepoint,導(dǎo)致profiler無(wú)法獲得該線程棧,導(dǎo)致錯(cuò)誤的profiler結(jié)果。幾個(gè)商用的profiler工具都存在上述問(wèn)題。但是,Oracle Solaris studio利用的是jvmti的一個(gè)非標(biāo)準(zhǔn)接口AsyncGetCallTrace來(lái)實(shí)現(xiàn),不存在上面問(wèn)題,Jeremy Manson也利用該接口 實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的profiler工具:lightweight-java-profiler。
?
相關(guān)知識(shí): 部分內(nèi)容摘自 http://blog.csdn.net/c395318621/article/details/55224665 部分內(nèi)容摘自 http://tacy.github.io/blog/2014/07/16/FlameGraph/ 部分內(nèi)容摘自 http://www.javashuo.com/content/p-6579579.html 部分內(nèi)容摘自 http://colobu.com/2016/08/10/Java-Flame-Graphs/ 文章: Evaluating the Accuracy of Java Profilers 文章:?Why many profilers have serous problems。 文章:?What is Java safepoint?
?
轉(zhuǎn)載于:https://www.cnblogs.com/xingzifei/p/7446264.html
總結(jié)
以上是生活随笔為你收集整理的Java FlameGraph 火焰图的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: (八)cmockery中的calcula
- 下一篇: Java多线程——不变性与安全发布