2017-10-13 121 views
1

我最近接受了任務,在我們的Java服務器中進行基準測試和優化內存利用率,同時修復了內存泄漏(如果有的話)。我們有4臺JVM服務器運行在一臺擁有15G物理內存和32G交換內存的計算機上。以下是free -m快照。瞭解JVM內存優化

   total  used  free   shared buff/cache available 
Mem:   15289  14786   392   1   110   342 
Swap:   32767  3776  28991 

如果我理解正確: -

  1. 大部分的物理內存在使用中,最交換存儲器是免費的。
  2. 實際上緩衝了很少量的內存。
  3. 我有48GB的虛擬內存

現在我的每個服務器是與-Xmx選項設置7G最大堆大小運行。以下是來自GC utils的

$ jstat -gcutil 8317 
    S0  S1  E  O  M  CCS  YGC  YGCT FGC FGCT  GCT 
    0.00 0.00 6.97 0.22 96.77 91.89  72 8.027 33 10.975 19.002 
$ jstat -gcutil 8332 
    S0  S1  E  O  M  CCS  YGC  YGCT FGC FGCT  GCT 
    0.00 0.00 5.17 50.76 96.57 91.65 274 51.001 51 179.106 230.107 
$ jstat -gcutil 8249 
    S0  S1  E  O  M  CCS  YGC  YGCT FGC FGCT  GCT 
    0.00 2.10 80.37 69.53 96.87 92.08 421 69.478 13 56.569 126.047 
$ jstat -gcutil 23875 
    S0  S1  E  O  M  CCS  YGC  YGCT FGC FGCT  GCT 
27.91 0.00 37.07 86.29 97.59 94.60 232 7.294  2 0.030 7.324 

輸出運行手冊全部GC後,它徹底解放年輕人和老一代的所有服務器。現在我需要幫助理解這個特點,基本上我是否正確地假設了以下內容?

  1. 對象移動取決於壽命和生存算作伊甸園 - > S0 - > S1 - > O.
  2. 三個服務器中有老根>楊將軍這是否意味着,全GC沒有運行足夠?
  3. 或者,我需要調整SurvivorRatio和NewRatio等設置,讓年輕一代有更多收集對象的機會,並延遲將對象移動到舊空間。
  4. 但是,增加Y空間意味着較慢的GC和較差的應用程序吞吐量,我應該增加內存並停止擔心調整嗎?

我在問這個問題,因爲Full GC會釋放所有內存,所以沒有內存泄漏,但是如何通過調整GC設置來平衡內存使用量和應用程序吞吐量。任何人都可以通過考慮上述機器狀態來提供更多方向或建議?

JVM Details: 
Java Version: openjdk version "1.8.0_131" Server Class 
GC: Parallel Collector(Default one) 

回答

2

總之:如果你想了解你的系統,基本上在某個時間點使用內存是一個壞主意。隨着時間的推移,觀察行爲會更有幫助。爲此,請使用JConsole或專業配置文件(如YourKit或JProfiler)。另一方面,Hotspot-VM的默認設置是非常合理的,所以除非你有一個非常具體的應用程序 - 內存配置文件,否則你可能不會因爲擺脫困境而贏得很多勝利,而只是通過拋出更多的硬件來贏得更多的勝利。

要知道,你的服務器是最prbably underdimensioned(見問題4)

龍答:

問題1:如何對象進行過不同的內存區域?每個對象都在伊甸園空間中創建。第一個小垃圾收集(這是引發了一個主要收集)將把這個對象或者在倖存者(如果有足夠的空間)或者直接放入終身。對於已經存活的對象,它們從一個倖存者空間移動到另一個倖存者空間,並且在某個點(由VM內的啓發式確定)移動到終身。規則總是成立,至少有一名倖存者永遠是空的。

問題2:老年人比年輕人有更大的職業意味着,你不經常收集足夠的?絕對不是。如果它很少執行,Java中的垃圾收集效果會更好(效率更高)。基本上,如果自上次收集以來更多的對象已經死亡,那麼這個集合會更高效,因爲它可以一次清理更多的內存。 gc的設計目的是讓使用者在觸發完整gc之前填滿,直到達到非常高的填充水平(接近100%)。我們觀察生產系統數週未完成gc,因爲年輕一代足夠大,所有臨時配置都會死在伊甸園或倖存者中。除此之外:你所有的緩存,Spring Beans或其他任何東西都將被放置在終身。

問題3:我應該調整內存參數來優化內存消耗嗎?無論如何:不!除非你確切地知道你在做什麼,否則千萬不要觸摸那些東西。擴大年輕一代可能會導致您的應用程序死於內存不足錯誤。在討論這些東西之前,你應該非常清楚你的應用程序的長期行爲以及熱點-VM的啓發式算法是否相當不錯。另一方面,如果你知道你在做什麼,可以大大減少gc時間。在一個系統(上面提到的系統)中,我們看到次要收集量從一次〜20秒減少到幾分鐘一次,並在調整後幾乎完全停止了全部gcs。但是在學習和理解的過程中,我們的應用程序隨着時間的推移如何表現記憶,我們也殺了很多處決。

問題4:我應該增加記憶而不是煩悶嗎?取決於。您的系統不健康,因爲它是。增加記憶會使情況變得更糟。您在具有16克物理內存的系統上運行4個虛擬機,堆上最多7克(總計28克)。如果所有虛擬機都將內存消耗擴大到最大,您將看到大量的交換,並將最終將性能降至您無法想象的水平。我會盡量在場景中尋找更多的硬件,特別是考慮到Java應用程序的實際消耗大約是堆的1.5倍(您必須添加permgen/metaspace,堆棧,codecache和vm自身消耗的內存)。如果您確定知道,您的應用程序使用-xmx7g運行,那麼您可以從這裏開始:在減少舊版部件的同時增加整體內存,以便絕對舊尺寸保持不變。但是,這意味着更多的硬件。

+0

感謝您的回答。然而,事情仍然清楚。整個焦點都是服務器都不需要7g的情況,只是YG沒有足夠的機會收集對象,並且OG運行頻率較低,因爲它通常是件好事。增加Y空間可能會解決這個問題。但它可能會增加YGCT。然而,我不清楚,YG的增加是如何導致OOM的?堆大小仍然保持不變。 –

+0

一旦有少量收集品存在,即將被撤離到終身位置,並且終身沒有足夠的空間來容納他們,就會發生OOM。基本上,對於OOM來說,年輕人是完全不相關的。較大的年輕空間會使次要收集次數減少(整個過程效率更高),但較大的年輕手段(相對)較小,可能會觸發OOM。 – Jonathan

+0

@MangatRaiModi我還沒有明白這一點:你認爲爲什麼gcs應該更頻繁地運行?通常在這方面進行優化時,您希望儘可能地減少採集頻率 - 這對於年輕人和老年人都是如此。 – Jonathan