2016-04-18 8 views
1

通常、〜20個のJVMで構成されるアプリケーションがあり、それらにバッチジョブを配布します。 20個のJVMは同じオペレーティングシステムで動作します。バッチジョブの1つにバッチジョブをディスパッチする前に、そのジョブがどのくらい長くどのくらい大きいかを知るのは難しいです。 1分または数時間かかることがあります。メモリ消費量も同様に変化します。複数のVMのガベージコレクション

これまでのところうまくいきましたが、合計40GBのメモリが利用可能です。各JVMの最大ヒープサイズは2GBに設定されています(2GBが必要な場合もあります)。同時に大量のバッチジョブを実行することは決してなかったため、メモリに関する問題は一度も発生しませんでした。私たちがJava 8のVMに移行するまで。完全なGCがあまり頻繁にトリガーされないようです。私たちは、JVMがアイドル状態になり、メモリ使用量が増加しています。 jcmdを呼び出してGCを起動すると、OldGenが1GBから200MBのようにダウンしているのがわかります。

これは、最大2GBのHeap + Stack + Metaspaceを持つ20個のJVMを持つための十分なセットアップではないことが分かりました。これは最大40GBのメモリよりもはるかに多くなります。しかし、それは私たちが生きなければならない状況です。また、複数のJVMのクラスタで最大のヒープサイズを設定する方法がある場合は、私は驚いています。だから私は他の解決策を考え出す必要がある。

VMに定期的に完全なGCを実行するように指示するVMオプションを探していましたが、これは私たちの問題を解決する可能性が非常に高いです。しかし、私はこれを行うVMオプションを見つけることができません。

メモリスワップを回避するためにこれを設定する方法についてのご意見はありますか?

編集:ここでは、GCログからの抜粋です:

2016-04-14T01:02:49.413+0200: 37428.762: [Full GC (Ergonomics) [PSYoungGen: 28612K->0K(629248K)] [ParOldGen: 1268473K->243392K(1309184K)] 1297086K->243392K(1938432K), [Metaspace: 120332K->120320K(1181696K)], 0.3438924 secs] [Times: user=1.69 sys=0.02, real=0.35 secs] 
2016-04-14T01:02:52.442+0200: 37431.792: [GC (Allocation Failure) [PSYoungGen: 561664K->67304K(629248K)] 805056K->310696K(1938432K), 0.0315138 secs] [Times: user=0.26 sys=0.00, real=0.03 secs] 
2016-04-14T01:02:54.809+0200: 37434.159: [GC (Allocation Failure) [PSYoungGen: 628968K->38733K(623104K)] 872360K->309555K(1932288K), 0.0425780 secs] [Times: user=0.35 sys=0.00, real=0.04 secs] 
... 
2016-04-14T10:09:03.558+0200: 70202.907: [GC (Allocation Failure) [PSYoungGen: 547152K->41386K(531968K)] 1545772K->1041036K(1841152K), 0.0255883 secs] [Times: user=0.18 sys=0.00, real=0.02 secs] 
2016-04-14T10:20:53.634+0200: 70912.984: [GC (Allocation Failure) [PSYoungGen: 531882K->40733K(542720K)] 1531532K->1042107K(1851904K), 0.0306816 secs] [Times: user=0.22 sys=0.02, real=0.03 secs] 
2016-04-14T10:23:10.830+0200: 71050.180: [GC (System.gc()) [PSYoungGen: 60415K->37236K(520192K)] 1061790K->1040674K(1829376K), 0.0228505 secs] [Times: user=0.17 sys=0.01, real=0.02 secs] 
2016-04-14T10:23:10.853+0200: 71050.203: [Full GC (System.gc()) [PSYoungGen: 37236K->0K(520192K)] [ParOldGen: 1003438K->170089K(1309184K)] 1040674K->170089K(1829376K), [Metaspace: 133559K->129636K(1196032K)], 1.4149811 secs] [Times: user=11.10 sys=0.02, real=1.42 secs] 

我々は毎時間、フルGCを持っていた場合、それが私たちの問題を解決するだろう、私は推測します。

+0

System.gc()?しかし、注意してください:それはまったく何かをすることは保証されていません、通常それはソリューションではないと呼んでいます。また、オブジェクトは古くなってしまいます。私は非常に古いオブジェクトは永遠にメモリに残っていると思います... – Exceptyon

+2

G1コレクタに完全なGCを実行させるのではなく、なぜ完全なGCを強制する必要がありますか? 2GBのヒープを使用でき、1GBしか使用していないときには完全なGCをトリガーしようとしています。それは奇妙に思える。実際には、JVMのチューニングを見て、少数のオブジェクトが古い世代になるようにすることができます。使用パターンを考えれば、大規模で長寿命のバッチは、 。 – sisyphus

+1

@Exceptyonいいえ、彼らは確かにしません。年齢に関係なく到達不能なオブジェクトが収集されます。 – Kayaman

答えて

1

時間トリガーGCを使用する代わりに、-XX:GCTimeRatio=14 -XX:MaxHeapFreeRatio=30 -XX:MixHeapFreeRatio=20で実行できます。これはコレクタにヘッドルームを少なくし、GCでより多くのCPUサイクルを費やすことができるようにすることで、ヘッドルームを少なくします。

現在のJDK9ビルドでは、これをさらに-XX:-ShrinkHeapInStepsと組み合わせると、割り当てられたヒープサイズが使用されたヒープをより詳細に追跡できるようになります。再び、パフォーマンスを犠牲にする可能性があります。

+0

を試してみると思います。これまでGCTimeRatioを理解していたので、これはGCで費やされた時間を制限するはずでした。実際にこのオプションを使用して、VMにGCとのより多くの時間を費やすように指示できますか? – EasterBunnyBugSmasher

+0

しかし、コレクタには、一時停止時間と時間比率の制約の後にのみ考慮されるインプリメンテーション・フットプリント・ゴールがあります。パラレルコレクタにはデフォルトで休止時間目標が設定されていないため、時間比率制約を緩和することでスループット目標を達成することがより積極的になります。より頻繁な収集につながる可能性のある他のオプションと組み合わせて使用​​します。 – the8472

2

無作為にGCを実行しても意味がありません。

GCをバッチの末尾(またはその後ろ)に追加します。この時点では、メモリを最小限に抑えてGCを高速化し、最良の収縮を得る必要がある可能性があります。

0

すべての回答/コメントに感謝します。 私が思いついた解決策は、たくさんの答え/コメントの組み合わせです。

@Peter Lawrey: バッチ処理が実行されるたびにSystem.gc()を呼び出すことは非常に意味があり、以前はこれを思い付かなかったことに驚いています。それだけではメモリの使用量を減らすことはできませんでした。私たちは、200GBのデータで満たされていた1GBの旧世代に過ぎないでしょう。

@ the8472: GCTimeRatioは、私たちを何らかの形で助けてくれていないようです。しかし、MaxHeapFreeRatioとMinHeapFreeRatioを両方とも40に変更しました。低い値を選択すると、Young Generationのサイズが大きく制限され、200MBを超えることはありませんでした。 両方のパラメータを同じ値に設定すると、メモリの割り当てと割り当て解除が多くなると思われますが、GCで1分の時間を費やしても、まだ<となっています。

@Sisyphus: newRatioを1に設定すると、Young GenerationとOld Generationに同じサイズのものが追加されました。これにより、GCのパフォーマンスが大幅に低下します。これはおそらく最高の利益をもたらす変更です。

+0

私たちはそれをしばらく実行していたので、newRatioを1に設定するのはひどい考えでした。 2GBのヒープでは、古い世代は1GBを超えることはありません。旧世代のフル1GBが使用されていても、新世代で600MB以上の空きメモリが残っていれば、メモリが使い果たされます。 – EasterBunnyBugSmasher

関連する問題