開發與維運

An Introduction to JWarmup

一、JWarmup背景 

(一)應用程序預熱 

Java的方法要被執行,首先這個方法所在的類需要被JVM加載,這個過程包括各類文件的驗證、解析、鏈接以及類的初始化。當這個類被加載進來了以後,JVM就可以去執行這個方法。 

JVM在剛開始的時候會使用模板解釋器去解釋執行方法,模板解釋器除了一個個去執行方法中的Bytecodes之外,還會額外收集關於方法執行動態運行的信息,例如方法執行的調用次數,調用時一些類型的信息等。這些信息都會提供給JVM的即時編譯器,由它利用這些信息將剛才解釋執行發現的熱點方法編譯成為Native Code。這樣JVM就不用模板解釋器去執行這些方法,而是去執行性能更高的Native Code,從而使應用程序的性能得到大幅提升。 

當大多數熱點方法都被編譯成為Native Code以後,應用程序的預熱就完成了 

 

(二)遇到的問題 

Java有非常豐富的應用場景,一個典型的場景就是我們會用Java寫一些 Web服務在Web服務的部署過程中,會發現預熱給我們帶來非常大的困擾。當我們把一個Web服務部署到線上後,應用啟動完成,此時就會有大量的用戶請求進入。 

這個時候由於有大量的熱點方法需要被編譯,JVM的編譯線程會非常忙碌,因為它需要佔用大量的CPU將這些方法編譯成為Native Code。同時又因為用戶的線程需要執行解決用戶的請求,因此它也會佔用大量的CPU,並且會搶佔編譯線程所使用的CPU,這樣就會導致編譯線程無法儘快把這些熱點方法編譯到Native Code,使得應用程序長時間運行在解釋執行的狀態,降低服務的質量同時服務的RT會增加,服務所使用的CPU也會非常的高,這就是在真實場景中所遇到應用程序預熱的問題接下來我們來看一下阿里巴巴Dragonwell 8中的JWarmup特性是如何解決這個問題。 

 

 

二、JWarmup功能 

image.jpeg 

上方為JWarmup流程圖,它將應用程序的發佈分成了兩個階段,分別是Recording和Replaying。在Recording階段,JVM會接受線上的請求,同時記錄JVM即時編譯器它所編譯方法的信息,並且將這些信息都輸出到一個文件之中。 

等到第二次再去啟動的時候,JVM就可以去讀取剛剛所記錄的這些方法編譯的信息,同時會主動的觸發即時編譯器編譯剛剛記錄的熱點方法,使得在用戶請求到來之前,就把熱點方法編譯成為性能較高的Native Code,避免了用戶請求大量進入的時候做編譯,這樣就能夠進一步提高應用程序的性能,節約CPU使用率。 

 

 

三、案例演示 

(一)Demo代碼 

image.png 

下面根據一個簡單的例子展示如何使用JWarmup功能 

上方為一個簡單的 Java程序,在這個程序之中有一個循環用來模擬線上應用的一個熱點,循環會反覆調用一個方法。 

 

(二)Recording 

如何去使用JWarmup的記錄功能Recording 

-XX:+CompilationWarmUpRecording 

-XX: CompilationWarmUpRecording=30 

-XX: CompilationWarmUpLogfile=./jwarmup.log 

-XX:-ClassUnloading 

第一個參數表示去打開JWarmup的記錄功能 

第二個參數表示需要記錄的時間,在當前Demo之中選擇記錄30秒 

第三個參數表示記錄編譯信息生成文件的路徑在這個Demo中,我們將這個文件生成在當前目錄下的jwarmup.log這個文件 

第四個參數由於JWarmup的Recording功能不支持ClassUnloading,所以需要將這一功能關閉。 

設定的記錄時間到了以後,JWarmup會將記錄好的編譯信息輸出到指定的文件之中,同時會在應用程序的輸出中看到以下這樣一條日誌,表明記錄是成功的。 

image.png 

 

(三)Replaying 

如何使用JWarmup的Replaying功能 

  • 添加JVM參數: 

-XX:+CompilationWarmUp 

-XX:+CompilationWarmUpLogfile=./jwarmup.log 

-XX:+PrintCompilationWarmUpDetail 

第一個參數表示使用JWarmup的編譯功能 

第二個參數需要指定剛剛記錄的包含編譯信息的文件,在當前Demo之中,就是剛剛所記錄的當前目錄下的jwarmup.log文件 

第三個參數表示我希望JWarmup打印出一些詳細的日誌,幫助我記錄JWarmup工具的一些行為 

當把這些參數配置好以後,將服務啟動,等待一些關鍵的類的加載完成可以使用jcmd <pid> JWarmup -notify主動觸發Warmup的編譯。 

Warmup編譯完成後,可以在程序的標準輸出中看到下面三條log,就表示這一次Warmup編譯是成功的 

image.png 

以上就是關於JWarmup的基本介紹,包含JWarmup所需要解決的問題,解決方法,以及用案例講述如何使用JWarmup功能同時我們對JWarmup這個功能還做了非常多的改進,形成了我們另外一份工作:JWarmup2 

image.png 

上方為JWarmup2整體流程圖,可以看到在這份工作之中,我們記錄了更加豐富的信息,去更好解決應用程序預熱的問題。 

首先我們會使用JFR(Java Flight Recorder)統一所記錄的編譯的信息,這些信息也可以形成一個JFR文件,使用JDK官方所提供的Java Mission Control瀏覽所記錄的所有熱點方法的信息 

此外我們除了記錄一些方法的編譯,還記錄了每一個方法它所依賴的類的信息。這樣子在我們第二步預熱的時候,就可以根據這些依賴的信息,當我們看到一個方法,它所有的依賴的類都被加載了以後,就會自動觸發這個方法的Warmup編譯,避免了人工手動觸發Warmup編譯 

此外我們還額外記錄了這些方法所有的Profiling信息,這些信息能夠幫助我們在第二步去更好地生成Warmup的代碼,從而進一步提高應用程序的性能 

JWarmup2未來將在阿里巴巴Dragonwell 11中開源,歡迎大家使用。 

Leave a Reply

Your email address will not be published. Required fields are marked *