jvm的代碼緩存耗盡導致性能下降


  在沒遇到這個問題之前,我對JVM的解釋模式與編譯模式的代碼性能相差有多大,是沒有感覺的,只是覺得編譯模式會比解釋模式性能好那么一點點吧。

但是經歷過這次以后,讓我對JVM的即時編譯產生了興趣。先來看看這個問題的背景:

  大概是4年前,我的團隊里有一個PM找我說他們遇到一個很奇怪的問題,在性能測試的時候,有幾個不同的測試場景混合在一起進行壓力測試,有時會出現測試幾十幾分鍾以后性能會下降的很厲害,一旦出現性能下降以后,性能再也回不到剛開始測試的水平。奇怪的是:它不是必現的,而且如果只是某1個或者2個場景一起測試的話,不會出現。

  因為不是網上問題,所以我有時間坐下來好好分析,先安排老思路排查,按我遇到的經驗一般性能瓶頸是某些資源遇到了瓶頸,這些瓶頸可以是磁盤IO、網絡IO、CPU、內存等,然后使用相應的Linux命令一一排查。在排查到CPU的時候,發現CPU比較高,然后使用jstack多次取堆棧進行分析,但是發現每次堆棧的棧頂都不太一樣,但是從棧頂再往下看,能看到都是停留在我們使用的一個商用軟件Volantis MCS的堆棧上。Volantis MCS即Volantis Multi Channel Server,它的作用是使用某種開發語言開發一個頁面,在用戶通過手機訪問時會根據用戶的手機的User-Agent自動轉換成最適合手機展示的xhtml頁面,就是我們常說的終端適配了。

  它與我們以往的不一樣的是以前出現的CPU高一般堆棧都是集中在某一個或者幾個方法上,而這次是分散在很多處,有點犯難了。

  由於是商用軟件,沒有源代碼,我只能把取到一些典型的堆棧記下來,然后反編譯代碼,看到經常在jstack上處於Runnable的棧頂的代碼並不是很復雜的邏輯,只有一些基本的字符串、+-*/這樣的運算。因為性能壓測tps比較高,直接使用JProfiler工具的話,性能是壓不上去的,只能拿出我的殺手鐧了: 把class反編譯以后,自己加了一些統計性能的代碼,並定期的打印出來。雖然方法有點土,但是直接有效。

  打印出統計日志以后,就發現問題所在了,同樣沒有任何IO操作的方法,在出現問題前調用一次在3~5ms,而出現問題以后這個方法平均時長為20~30ms。難道是輸入不一樣嗎?隨后又增加日志把輸入也打印出來,發現完全一樣。

  同樣的輸入,同樣的代碼,竟然性能相差這么大,難道是機器上有其它進程(線程性能影響),排查了也沒有呀。

  這時突然靈光一現,是不是因為這段代碼在一定情況下沒有編譯成本地代碼,而是在解釋模式下運行的?是不是編譯代碼時也有緩存大小,在網上查了一下我所用的JDK版本的默認的代碼緩存是64M,在官方找到了對應版本的配置,並根據網上的信息如果發生這種問題,會在gc日志會打印一句warning,具體的warning是什么忘記了。反正我們的機器的內存配置一般至少都是32G,代碼緩存配置為128M也不為過,配置了以后不論怎么測試都OK了.

   回過頭了想想為什么會有時出現有時沒有?猜測原因大概是這樣的,因為我們應用代碼量非常大,使用了很多第三方軟件,特別是Volantis MCS這樣非常耗CPU的組件執行的頻率如此之頻繁,在某一種場景下,如果先測試某個流程會導致那個流程中大量的代碼被轉換成本地代碼,然后再執行這些非常頻繁的代碼的時候代碼的緩存因為耗盡了,就只能采用解釋的方式執行。

  事情到這里其它我最感興趣的地方才剛開始:

  1、解釋模式與編譯模式性能究竟相差多少?

  2、為什么編譯以后的代碼性能這么高?

  第一個問題我做了測試,把JVM的配置修改為純解釋模式,原來幾分鍾啟動的應用,等了有20分鍾左右還沒有完全啟動起來,要知道我們用的服務器一般至少都是4核心的。第二個問題,下載了openjdk的代碼,看了x86的c++的代碼,發現太復雜了,當時放棄繼續研究。直到去年的時候,我離開華為的時候有了一些自己的時間,自己買了一本《Hotspot實戰》並在iteye上有一個高級虛擬機的組的一些前阿里大神的一些文章,結合openjdk 8的代碼,才慢慢對編譯的原理有些感覺。為什么性能相差這么大,我的理解解釋模式采用套用代碼調用的模板,每一個指令選擇一個template,把執行的template的匯編代碼打印出來,可以看出來一個很簡單的指令都會生成一堆指令。而編譯模式有C1和C2 2層優化(http://hllvm.group.iteye.com/group/topic/39493),JVM先把匯編指令轉換成一種中間的代碼格式ad,再采用傳統的編譯器的優化優化技術,這些優化技術是集國外的各大神的技術精髓,所以它重新生成的代碼比你手工寫的代碼質量高就一點不奇怪了。

  隨着逐步深入,發現原來JVM的GC又是一塊寶藏。話題有點扯遠了,發現自己懂的太少了,JVM里面好玩的東西太多了,學習中...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM