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的部落格

歡迎關注我的公眾號:程式那些事,更多精彩等著您!