jvm的代碼緩存耗盡致使性能降低

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

可是經歷過此次之後,讓我對JVM的即時編譯產生了興趣。先來看看這個問題的背景:c++

  大概是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的組件執行的頻率如此之頻繁,在某一種場景下,若是先測試某個流程會致使那個流程中大量的代碼被轉換成本地代碼,而後再執行這些很是頻繁的代碼的時候代碼的緩存由於耗盡了,就只能採用解釋的方式執行。優化

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

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

  二、爲何編譯之後的代碼性能這麼高?

  第一個問題我作了測試,把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裏面好玩的東西太多了,學習中...

相關文章
相關標籤/搜索