使用JRockit Mission Control進行效能分析和調優

weixin_34319999發表於2017-11-15
Mission ControlBEA JRockit JVM自帶的一組以極低的開銷來監控、管理和分析生產環境中的應用程式的工具。它包括三個獨立的應用程式:記憶體洩漏監測器(Memory Leak Detector)、JVM執行時分析器(Runtime Analyzer)和管理控制檯(Management Console)。BEAJRockit R26版本就開始捆綁這個工具套件,目前最新的版本是3.0。最近我們使用其中的Runtime Analyzer對國內某著名行業解決方案進行性分析和調優。
 
JRockit Runtime AnalyzerJRA)是一個JVM分析器,是一個隨需應變的“動態記錄器”。它記錄了Java應用程式和JVM在一段預定的時間內的詳細記錄。然後通過JRA應用程式對記錄下來的檔案進行離線分析。所記錄的資料包括對方法的呼叫跟蹤、錯誤的同步、鎖定的分析,還有垃圾收集統計資訊,優化決策以及物件統計資訊和其他重要的應用程式/JVM行為。它的目的是讓JRockit開發人員能夠找到良好的方法來基於現實應用程式優化JVM,對於幫助客戶在生產和開發環境中解決問題十分有用。
 
2.效能資料分析和調優
 
在本次專案中,操作|A和操作B的百人併發指令碼執行完成的時間接近兩分鐘,因此我們使用JRA進行了2分鐘(120)的記錄。在GC常規資訊中,我們發現在短短兩分鐘時間內,垃圾收集的總數高達365次,而由此造成的暫停時間有42.5秒之多。也就是說35%的執行時間是在做垃圾收集。
 
因為最大堆尺寸已經設定成1024M,對於32位作業系統上的Java應用已經是足夠大了(在IA32構架下,由於作業系統給每個程式的最大記憶體定址空間為1.8G,因此最大堆尺寸不能超過1.8G),因此堆的大小並不是造成頻繁垃圾收集的原因。那麼在高併發度的場景下,可能的影響因素很可能是Nursery大小。
 
Nursery 也稱為新代,是指執行分代式垃圾收集器時,在堆中分配 新物件 的可用塊區域。 Nursery 變滿時,會在新垃圾收集中單獨對其進行垃圾收集。Nursery 大小決定了新收集的頻率和持續時間。較大 Nursery 會降低收集的頻率,但是會稍微增加每個新收集的持續時間。 Nursery 之所以具有價值,是因為 Java 應用程式中的大多數物件都是在新代中夭亡的。與收集整個堆相比,應首選從新空間中收集垃圾,因為該收集過程的開銷更低,而且在觸發收集時,新空間中的大多數物件均已死亡。在新收集過程中,JVM 首先確定 Nursery 中的哪些物件是活動的,此後將它們提升到舊空間,並釋放 Nursery,供分配新的小物件使用
 
Nursery的預設預設值是10M/CPU,對於我們Clovertown伺服器來說,只有20M。由於出現頻繁收集的情況,那麼我們推斷是由於Nursery的預設值太低的原因。一方面在高併發使用者的場景下,肯定是有大量的新物件產生,那麼Nursery的空閒空間很容易就被耗盡。因此Nursery發生垃圾收集頻率就會比較高。另一方面更短的垃圾收集間隔會使得新物件在Nursery的存活率提高因為很多新物件可能還沒來得及使用完畢就已經發生垃圾收集。這樣更多的物件會被提升到舊代,使得舊代的物件也會急劇增加,從而使得舊代發生垃圾收集的頻率也增加。
 
因為JRockit JVM可以使用-Xns:<size>來設定Nursery的尺寸,我們要在保證垃圾回收停頓時間(garbage collection-pause)儘可能短的同時,儘量加大Nursery的尺寸,這在建立了大量的臨時物件時尤其重要。推薦值是最大堆尺寸的10%,因此我們在JRockit的執行時引數上新增了 –Xns100m。再次執行指令碼後,JRA收集的資訊顯示GC暫停時間驟降到15.3s,次數也有所減少,降到296
 
Nursery大小
20M(預設值)
100M
GC暫停時間
42.5s
15.3s
垃圾收集的總數
365
296
平均暫停時間
116ms
52ms
 
此外,我們從方法資訊中可以看到呼叫次數最多耗時間最長的兩個方法分別是jrockit.vm.Locks.monitorEnterSecondStagecom.ABC.StateManager.makeState兩個方法。展開前置任務後發現呼叫這兩個方法最多的方法是com.ABC.SqlQueryAction.query。而jrockit.vm.Locks.monitorEnterSecondStage顯然是JRockit實現鎖機制的特定的API。因此我們懷疑是對資料庫的操作時有資源互斥的現象發現。
 
考慮到高併發使用者的場景下,對資料庫操作的併發度也很高,因此對資料庫連線的爭用比較激烈。我們察看了一下當時WebLogic JDBC的配置,發現connection pool的大小隻是預設值20,相對來說偏小了,對效能會有一定的影響。因此我們增大connection pool的大小到100。重新執行測試指令碼後發現效能有較大提升。
 
 
 
JDBC connection size 20  w/ default nursery
JDBC connection size 100 w/ 100M nursery
Increase %
 
操作A
22.125
12.079
83%
操作B
35.195
21.773
62%
 
 
在效能調優完成後,我們又進行了功能測試(迴歸測試),以驗證上述改動沒有影響系統的功能性正確。
四、小結
其實利用Mission ControlJava應用進行調優並不難,對吧?希望本次效能分析調優的過程可以給大家一些啟發,今後可以應用到日常工作中。

本文轉自Intel_ISN 51CTO部落格,原文連結:http://blog.51cto.com/intelisn/130730,如需轉載請自行聯絡原作者

相關文章