JIT的Profile神器JITWatch
簡介
老是使用命令行工具在現代化社會好像已經跟不上節奏了,尤其是在做JIT分析時,使用LogCompilation輸出的日誌實在是太大了,讓人望而生畏。有沒有什麼更加簡便的方法來分析JIT日誌呢?快來和小師妹一起來學習JITWatch吧。
什麼是JIT
小師妹,F師兄,JIT就是Just In Time compilers。能不能再總結一下JIT到底是做什麼的呢?
當然沒問題,JIT主要有兩個作用,第一個作用大家應該已經知道了,就是在運行時將byte code編譯成為機器碼,提高程序的執行速度。
第二個作用就是在運行時對代碼進行優化,同樣的也對性能進行提升。
JIT中有兩種編譯器,C1代表的是Client Compiler,C2代表的是Server Compiler。
其中C1隻是簡單的編譯,而C2在收集到更多信息之後,會進行更加深入的編譯和優化。
常見的優化手段有:Loop unrolling, Inlining, Dead Code Elimination,Escape analysis, Intrinsics, Branch prediction等。
JDK8中會默認啟動分層編譯。你也可以使用-XX:+TieredCompilation來手動啟動它。
JITWatch簡介
小師妹:F師兄,上次你講的LogCompilation和PrintCompilation輸出結果還是太複雜了,尤其是LogCompilation,輸出的結果有十幾M,分析起來好難。有沒有更簡單一點的辦法,讓我的工作效率加倍呢?
這個必須有,有需求就有市場,有需求就有大神出場。今天給你介紹一個工具叫做JITWatch。
JITWatch是一個大神做的JIT日誌的可視化分析工具。在使用它之前你可能覺得它有點強大,在使用後你就會覺得它真的是強大。
運行JITWatch
小師妹:F師兄,這麼強大的工具,快快介紹我使用吧。
完全沒有問題,不過JITWatch沒有現成的打包好的可執行文件。沒錯,你需要到github上面下載源碼。
下載完畢,可以執行:
mvn clean compile test exec:java
就可以開啟JITWatch之旅了。
JITWatch詳解
小師妹:F師兄,這麼好用的工具為什麼不打個包出來讓大家直接用呢?還要下載源碼這麼麻煩。
其實吧,JITWatch為了大家方便使用,自帶一個Sandbox功能,提供了一些可以直接在JITWatch中運行的代碼,同時JITWatch可以實現源碼的實時比對功能。所以需要大家下載源碼。
閑話休提,我們開啟JITWatch之旅吧。
入眼就是如此樸實無華的界面,讓人感覺總有點…重劍無鋒,大巧不工。高手做的UI就是這麼的完美。
接下來我們需要運行一個程序,來實時感受一下JITWatch的魅力。
看到左邊最上角的sandbox了嗎?點開它可以看到下面的sandbox頁面:
這一個頁面會選擇一個sadbox中的例子展示給你,大家注意下面的輸出框的說明,它會顯示你的Disassembler是否可用。如果想要安裝disassembler,請參照我之前的文章。
如果你對這個例子不滿意,或者你想使用自己的代碼,那也完全沒有問題。點擊config。
這裡你可以配置源代碼的路徑,可以選擇VM的語言,還有各種VM的選項,下面的選項相信我在之前的文章中都已經介紹過了吧。
如果還有不懂的小夥伴,微信我,私聊我,1對1現場教學。
萬事俱備,只欠東風,開始吧,我可是要成為Java王的男人!
然後我們就進入了TirView界面,這裡我們可看到主界面分成了三部分,源代碼,ByteCode和Assembly。
小師妹:真是熱淚盈眶啊,終於不需要自己去添加那些XX參數了。面向界面編程,真好。
上面還有幾個按鈕,這裡簡單介紹一下他們的功能,具體的界面這裡就不截圖了,因為實在是太多了….
Chain會展示調用鏈。
Journal就是之前使用LogCompilation產生的xml日誌。
LNT,全稱是line number table。—目前我還不知道這個是做什麼用的,有知道的朋友,請給我留言。
然後就是Inlined into功能了,這個功能要詳細講一下,因為會影響到程序的執行效率。
還記得之前舉的inline的例子嗎?
int a = 1;
int b = 2;
int result = add(a, b);
...
public int add(int x, int y) { return x + y; }
int result = a + b; //內聯替換
上面的add方法可以簡單的被替換成為內聯表達式。
JITWatch可以顯示方法是否被inlined,並且顯示出inlined的原因。
點擊BCI可以顯示關聯的inlined的代碼。大家自行體會。
現在再讓我們回到可愛又有風格的主頁面:
左邊是源代碼,包含了JDK自己的代碼,如果你想詳細的分析JDK自己代碼的優化,那麼這是一個非常好的工具。
右邊顯示的是被JIT編譯的類和方法,並且展示了編譯級別和編譯的時間。
右上角又有一排按鈕,Config是用來配置運行的代碼。
TimeLine是以圖形的形式展示JIT編譯的時間軸。
Histo是直方圖展示的一些編譯信息。
TopList裏面是編譯中產生的一些對象的或者數據的排序。
Cache是free code cache空間。
NMethod是native方法。
Threads是JIT編譯的線程。
TriView就是我們最開始展示的面板。
最後我們重點講一下Suggestion:
Suggestion是對代碼的一些優化建議。
從上圖我們可以看到在調用String的hashMap方法時候無法inlined,因為被調用的方法太大了,超出了最大inlining size。
總結
所以,我們通過JITWatch可以學到什麼呢?最最重要的是我們可以通過JITWatch來分析JIT的運行原理和本質。然後inlined的方法不要太大了,否則影響執行效率。
本文作者:flydean程序那些事
本文鏈接://www.flydean.com/jvm-jit-jitwatch/
本文來源:flydean的博客
歡迎關注我的公眾號:程序那些事,更多精彩等着您!