7

特定のメモリ使用量でジョブを作成するJavaアプリケーションがあります。若い世代のヒープ設定のほぼ 80% でアプリケーションを起動すると、アプリケーションはデフォルトの 1:2 設定よりもはるかに高速に動作することに気付きました。特に、次のコマンドで jvm を起動しています。

java -XX:NewSize=10G -XX:+UseParallelOldGC -server -Xmx12G -Xms12G

サーバーには少なくとも 14 Gb の空き物理メモリがあるため、Java ヒープと「その他の」スペースには十分だと思います。

今、物事は次のように起こります:

25.289: [GC [PSYoungGen: 7872317K->1058813K(9175040K)] 7872533K->1059029K(11272192K), 0.1876420 secs] [Times: user=1.92 sys=1.01, real=0.18 secs]
28.918: [GC [PSYoungGen: 8923133K->1091124K(9175040K)] 8923349K->1091340K(11272192K), 0.2206940 secs] [Times: user=1.92 sys=1.70, real=0.22 secs]
32.946: [GC [PSYoungGen: 8955444K->1060567K(9175040K)] 8955660K->1060783K(11272192K), 0.1804050 secs] [Times: user=2.86 sys=0.01, real=0.18 secs]
37.166: [GC [PSYoungGen: 8924887K->1080085K(8329344K)] 8925103K->1080301K(10426496K), 0.1891370 secs] [Times: user=3.08 sys=0.01, real=0.19 secs]
41.326: [GC [PSYoungGen: 8098709K->1088209K(8106880K)] 8098925K->1088425K(10204032K), 0.2284920 secs] [Times: user=3.49 sys=0.04, real=0.23 secs]
45.779: [GC [PSYoungGen: 8106833K->59784K(8672768K)] 8107049K->1039790K(10769920K), 0.2195770 secs] [Times: user=2.02 sys=1.91, real=0.22 secs]
49.963: [GC [PSYoungGen: 6953352K->75043K(8689664K)] 7933358K->1062837K(10786816K), 0.0384440 secs] [Times: user=0.63 sys=0.01, real=0.04 secs]
54.171: [GC [PSYoungGen: 6968611K->140387K(8737984K)] 7956405K->1129497K(10835136K), 0.0715690 secs] [Times: user=1.12 sys=0.00, real=0.07 secs]
58.455: [GC [PSYoungGen: 7093923K->194024K(8701312K)] 8083033K->1205300K(10798464K), 0.0952730 secs] [Times: user=1.66 sys=0.02, real=0.10 secs]
62.825: [GC [PSYoungGen: 7147560K->122912K(8840256K)] 8158836K->1298466K(10937408K), 0.1671770 secs] [Times: user=2.89 sys=0.10, real=0.16 secs]
67.302: [GC [PSYoungGen: 7270304K->117888K(8792896K)] 8445858K->1377169K(10890048K), 0.1156200 secs] [Times: user=1.98 sys=0.05, real=0.12 secs]
71.785: [GC [PSYoungGen: 7265280K->119002K(8950720K)] 8524561K->1464556K(11047872K), 0.1152940 secs] [Times: user=1.97 sys=0.09, real=0.11 secs]
76.448: [GC [PSYoungGen: 7477018K->206455K(8893056K)] 8822572K->1642652K(10990208K), 0.1607870 secs] [Times: user=2.63 sys=0.06, real=0.16 secs]
81.051: [GC [PSYoungGen: 7564471K->114350K(9084608K)] 9000668K->1649307K(11181760K), 0.1145730 secs] [Times: user=1.89 sys=0.16, real=0.12 secs]
86.020: [GC [PSYoungGen: 7739630K->125895K(9026432K)] 9274587K->1743248K(11123584K), 0.1125030 secs] [Times: user=1.95 sys=0.06, real=0.11 secs]
91.007: [GC [PSYoungGen: 7751175K->202320K(9221952K)] 9368528K->1905769K(11319104K), 0.1523180 secs] [Times: user=2.58 sys=0.06, real=0.15 secs]
95.817: [GC [PSYoungGen: 8085136K->327488K(9146624K)] 9788585K->2203753K(11243776K), 0.2542190 secs] [Times: user=4.44 sys=0.10, real=0.25 secs]
96.071: [Full GC [PSYoungGen: 327488K->0K(9146624K)] [ParOldGen: 1876265K->1032314K(2097152K)] 2203753K->1032314K(11243776K) [PSPermGen: 27528K->21277K(48128K)], 1.4351920 secs] [Times: user=5.12 sys=0.36, real=1.44 secs]

ご覧のとおり、すべて問題なく、フル GC も正常に動作しています。しかし、次に発生するGC(フルではない)により、プロセスのメモリ使用量が劇的に増加し、サーバーはスワップを使用し始めます。

102.741: [GC-- [PSYoungGen: 7882816K->7882816K(9146624K)] 8915130K->9979962K(11243776K), 133.4433280 secs] [Times: user=69.73 sys=602.83, real=133.46 secs]
236.191: [Full GC [PSYoungGen: 7882816K->0K(9146624K)] [ParOldGen: 2097146K->1069237K(2097152K)] 9979962K->1069237K(11243776K) [PSPermGen: 21277K->21251K(48192K)], 6.9285350 secs] [Times: user=12.75 sys=0.23, real=6.93 secs]

問題は - なぜですか?私が理解している限りでは、フル GC は GC 処理で最も苦痛なポイントです。では、完全な gc が正常に実行された後にアプリケーションが停止するのはなぜですか?

4

2 に答える 2

2

システム時間が非常に長い(ユーザー時間よりはるかに長い)ことを考えると、これはOSで何かが起こっていることを示唆しています。十分なメモリがあると言いますが、JVMのごく一部でもディスクにスワップされると、GC時間が停止する可能性があります。

OS /ディスクキャッシュ/その他のプログラム用の空きメモリを確保するために、ヒープの合計サイズを減らすことをお勧めします。

アプリケーションをさらに改善するために、メモリプロファイラーを使用します(ほとんどの場合、コマーシャルを使用する必要があります。評価ライセンスで十分です)。毎秒1.5 GBのガベージを生成しているようですが、これは信じられないほどの量です。1秒あたり数100MBに削減できれば、パフォーマンスが大幅に向上します(遅延が減少します)。

ところで:-server64ビットマシンのデフォルトである必要があります。

于 2013-01-15T14:45:42.427 に答える
2

私は数年間、あなたと同様のヒープ サイズとメモリ チャーン (20 GB ヒープ、1 GB+/秒チャーン) を必要とするアプリケーションを使用してきました。@Peter Lawrey が言ったように、総メモリ消費量または解約率のいずれかを削減できれば、優位に立つことができます (参考までに、私は YourKit プロファイラーで幸運に恵まれました。会社とは関係ありませんが、私の経験では良かった。YMMV.)

しかし、実際にヒープの使用量やチャーンを減らすことができない場合は、さらに GC のチューニングを検討することをお勧めします。あなたは明らかにいくつかのことをしました。ここに私たちのために働いたいくつかのことがあります:

  • 新しい世代のサイズを減らします (現在 10 GB を割り当てており、数秒ごとにほぼすべてを収集しています。1 ~ 2 GB を割り当てて、より頻繁に収集する方がよい場合があります。これにより、合計ヒープ サイズを次のように減らすことができます。まあ、おそらくスワッピングを避けてください。

-XX:+PrintGCDetails -XX:+PrintGCDateStamps- GC ログに実際の日付があると便利な場合もあります)

-XX:+UseConcMarkSweepGC- 同時旧世代 GC はより多くの CPU を消費しますが、一時停止は短くなります。私たちのアプリケーションでは、それが私たちの好みであり、おそらくあなたのものでもあるように思えます.

また、ハードウェアに適した値に設定-XX:ParallelGCThreads=<threads>することもできます (12 コアのマシンで 6 を使用していますが、それが最適に調整されているかどうかはわかりません)。

于 2013-01-15T17:23:59.743 に答える