java vm_Java VM –提防YoungGen空间
java vm
正如您從我們以前的面向性能的文章中可能已經看到的那樣,運行良好的JVM是實現最佳應用程序性能和穩定性的最重要目標之一。 這樣的健康評估通常僅關注主要收集的頻率(避免)或檢測內存泄漏的存在。 年輕一代空間或短壽命物體的大小和足跡如何?
本文基于一個真實的故事和我們與一位IT客戶的最新故障排除經驗。 它將通過一個示例應用程序證明,過多的內存占用空間和次要收集的頻率可能會引發性能問題,就像其老兄,舊一代或使用期限的空間一樣嚴重。
JVM健康狀況診斷
如果您不熟悉JVM調優領域,那么您很快就會意識到,沒有適用于所有應用程序的通用解決方案。 無論您可以從各種來源從Web上找到高質量的材料,您都仍然需要進行盡職調查并正確了解要處理的應用程序類型,包括其對JVM GC暫停的敏感性(某些應用程序需要較低的JVM暫停時間<1%)。
Java性能分析(包括內存泄漏檢測)以及性能和負載測試是為收集所有正確數據以及有關應用程序內存占用量和JVM運行時運行狀況的事實而需要執行的額外工作的良好示例。
話雖這么說,“健康的” JVM是什么意思? 請盡您所能回答以下問題。
**如果回答“否”,請假設置信度為90%+,否則回答“我不知道”。
- 您的Java堆或OldGen空間是否隨著時間的流逝而泄漏(在進行重大收集之后)?
- 您的應用程序當前是否受到大型和/或頻繁的JVM GC暫停的影響?
- JVM的總體暫停時間是否高于5%或高于已建立的理想基準?
- 當前,您的應用程序響應時間是否經常受到JVM GC活動的定期影響,并且超出了應用程序的承受能力?
- 在最近3個月中,您是否觀察到java.lang.OutOfMemoryError錯誤的發生?
- 您是否在最近3個月內觀察到JVM崩潰的發生(帶有核心轉儲和崩潰報告的JVM突然故障)?
- 您是否認為您的JVM當前不穩定并且/或者需要過多的人工干預(定期重啟等)?
如果您回答“是”或“我不知道”,這意味著您或您的生產性能調整團隊可以在這里做一些工作,包括查看當前的JVM GC策略。
如果您對所有具有高置信度級別的用戶回答“否”,則意味著您可能已經獲得了可靠的應用程序和JVM穩定性,祝賀您。 我仍然建議您在主要版本和增量負載預測之間重新評估情況。
青年一代:真的停止世界嗎?
正如我們從快速的JVM健康狀況評估練習中看到的那樣,要點之一是指JVM的總體暫停時間。 這實質上意味著JVM在“停止世界”事件中花費了多少時間。 在此期間,應用程序線程將被掛起并且不執行任何工作,從而增加了應用程序的響應時間。 該指標至關重要,因為較大的JVM暫停將觸發不穩定且不可預測的響應時間。
我在過去幾年中看到的一個普遍誤解是,YoungGen或次要集合是完全透明的,并且不會影響應用程序的響應時間。 如果您的Java堆大小較小(YG空間<1 GB),并且處理的對象生存期或分配率適中,則此語句幾乎是正確的。 在這種情況下,如果次要集合執行得非常快(<20 ms)并且執行得不太頻繁(每30秒以上),則YoungGen空間貢獻的JVM總體暫停時間將保持很小(<< 1%)。 但是,如果YG內存分配率提高(每個請求的占用空間增加,流量激增等),情況可能會很快改變。
我建議以下文章,以獲取有關可用于HotSpot JVM的YoungGen空間和并發收集器的更多詳細信息。
#Oracle HotSpot主要是并發收集器:CMS vs. G1
- http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html
#Oracle HotSpot次要收藏全面介紹
- http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
- http://blog.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots_02.html
無論您使用的HotSpot GC策略如何,包括大多數并發的收集器(例如CMS或G1),YoungGen空間收集仍然是“世界停止”事件。 據我們所知, Azul Zing C4是唯一宣傳為真正的連續并發壓縮收集器的JVM收集器。 目前,我們還沒有機會嘗試使用該收集器。 我歡迎任何具有C4調優經驗的人分享他們的觀察結果,尤其是真實的事實數據,而不是像G1這樣的大多數并發收集器。
現在,我們已經涵蓋了一些理論,下面讓我們深入研究示例應用程序,并針對各種YoungGen占用空間和分配比率來回顧性能測試結果。
樣本應用規范
為了比較各種YG分配率之間的響應度和JVM暫停時間%,我們根據以下規范創建了一個示例應用程序:
- 根據以下屬性,已通過jvm URI創建并公開了JAX-RS(REST)Web服務。
每次對jvm的調用都執行以下邏輯:
1.分配短期對象的預定大小(適用于快速YG GC)。
此外,在類加載時會分配1 GB的長壽命對象(不適合GC)的初始內存占用空間,以便為CMS收集器創建一些噪音。
YG短期對象的內存分配和OldGen靜態保留僅通過按照下面的代碼片段創建原始字節值的靜態數組即可實現。 根據使用MAT的JVM堆轉儲分析,可以觀察到真正的內存占用量。
private final static int LONG_LIVED_OBJ_FOOTPRINT = (1024 * 1024 * 1024); private final static int SHORT_LIVED_OBJ_FOOTPRINT = (100 * 1024 * 1024);// 1 GB static memory footprint private final static byte byteArrayLongLivedObj[] = new byte[LONG_LIVED_OBJ_FOOTPRINT];// 100 MB memory allocation (waste) created per execution public void generateShortLivedObj(String objId) { byte byteArrayShortLivedObj[] = new byte[SHORT_LIVED_OBJ_FOOTPRINT]; }
最后,在下面找到環境規格和用于創建,執行和監視此YG比較性能測試的軟件。
- 作業系統:Windows 7 @ 64-bit
- Java EE容器: WildFly 8 Beta1
- JVM:Oracle HotSpot 1.7 @ 64位,Java堆大小為5 GB(YG空間:1152 MB XX:NewRatio = 3)。 GC收集器:CMS
- IDE: JBoss Developer Studio 7.0.0.GA
- JVM監視: JVisualVM
- JVM內存泄漏分析器: Plumbr 3.0
- JVM verbose:gc日志分析器: GCMV
- 性能和負載測試: Apache JMeter 2.9
性能測試結果和觀察
以下性能測試模擬了一個現實生活中的應用程序,該應用程序需要處理大量的JVM暫停時間以及在峰值負載下的嚴重降級。 在模擬每個請求的應用程序內存占用量的改善(減少)之后,執行了3次運行,其中1次作為基線運行,另外2次運行。
基準線
- 10個并發線程
- 每個JVM進程每次執行創建100 MB的短期對象
壽命短的對象的內存占用空間可能看起來很極端,但這確實是我們最初要解決的問題。
結果
- 平均響應時間:140毫秒
- 吞吐量:68請求/秒
- JVM總體暫停時間: 25.8%
- YG收集頻率:每秒7個收集
- GC速度:每分鐘308909 MB
按照JVisualVM,JVM看起來很健康(沒有內存泄漏,穩定且OldGen低等)。 但是,當您在verbose:gc日志中進一步深入研究時,您會意識到JVM的總體暫停時間為25.8%,這都是由于YG收集頻率過高所致。 這有力地證明了正確分析verbose:gc日志與僅關注JVM持久空間趨勢的觀點。
測試與調整#1
- 10個并發線程
- 每個JVM進程每次執行創建50 MB的短期對象
此運行模擬了應用程序占用空間和內存分配速率從每個分配的100 MB到50 MB的初始改善。 通過簡單地減少每個請求的應用程序內存占用量,我們可以清楚地看到所有數字的改進,特別是吞吐量。
結果
- 平均響應時間:119 ms -21
- 吞吐量:79要求/秒+11
- JVM整體暫停時間: 15.59%-10.21
- YG收集頻率:每秒3-4次收集-3
- GC速度:每分鐘164950 MB -143959
測試與調整#2
- 10個并發線程
- 每個JVM進程每次執行創建5 MB的短期對象
此運行模擬了將應用程序占用空間和內存分配率從100 MB大大降低到每個分配僅5 MB的情況。
結果
- 平均響應時間:107毫秒-33
- 吞吐量:90請求/秒+22
- JVM總體暫停時間: 1.9%-23.9
- YG收集頻率:每2-3秒收集1次*大幅減少
- GC速度:每分鐘15841 MB -293068
如您所見,對應用程序占用空間和內存分配的最終改進確實將JVM暫停時間顯著減少到了可接受的1.9%。 重要的是要注意,在這3個測試中,OldGen占用空間和CMS活動對JVM暫停時間沒有任何實質性影響,性能問題是由于活動過多以及與YG相關的世界停止事件數量過多所致集合。
解決方案和建議
我們的問題案例表明,通過調整和減少每個應用程序請求的內存占用空間,可以減少與過多的YG收集活動相關的JVM暫停時間,從而降低分配率和YG GC頻率。
但是,當短期內無法使用這種調整策略時,值得探索其他解決方案。 通過以下能力改進策略可以潛在地獲得類似的結果:
- 水平和垂直擴展:通過增加JVM進程數量來拆分流量,但以可用硬件為代價,從而降低了YG集合的分配率和頻率。 從本質上講,這意味著將硬件投入該問題。 我的建議始終是先微調您的應用程序內存占用量,然后并行探索其他擴展選項。
- Java堆大小和YG比率調整:增大YG空間的大小肯定會有助于減少停止世界YG集合的頻率。 現在請注意,不要“餓死” OldGen空間,否則您將直接解決問題,并產生更嚴重的后果,例如JVM抖動和OOM事件。
最后的話
我希望您喜歡這篇文章,并且現在更好地了解過多的JVM YG集合對性能的潛在影響。
我建議您閱讀本文后做以下練習:
- 選擇您最繁忙的應用程序之一。
- 查看verbose:gc日志,并通過GCMV確定JVM暫停時間。
- 確定YG收集的頻率和影響,并確定調整機會。
期待您的意見,并分享您的JVM調優經驗。
翻譯自: https://www.javacodegeeks.com/2013/11/java-vm-beware-of-the-younggen-space.html
java vm
總結
以上是生活随笔為你收集整理的java vm_Java VM –提防YoungGen空间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吃一堑长一智怎么读 吃一堑长一智如何读
- 下一篇: Java生产监控的阴暗面