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