フルGCが非常に頻繁になる

私は1つのTomcatインスタンス上でJava Webアプリケーションを実行しています。ピーク時には、webappは毎秒約30ページ、通常は約15ページを処理します。

私の環境は:

O/S: SUSE Linux Enterprise Server 10 (x86_64)
RAM: 16GB

server: Tomcat 6.0.20
JVM: Java HotSpot(TM) 64-Bit Server VM 1.6.0_14
JVM options:
CATALINA_OPTS="-Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m
               -XX:+UseParallelGC
               -Djava.awt.headless=true
               -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"
JAVA_OPTS="-server"

数日間の稼働後、Full GCがより頻繁に開始され、アプリケーションの可用性にとって重大な問題になります。クラウドの再起動後、問題は解消されますが、もちろん、5〜10日後または30日後に戻ってきます(一貫性がありません)。

The Full GC log before and after a restart is at http://pastebin.com/raw.php?i=4NtkNXmi

Full GCが2.5秒必要で、6秒ごとに起きていたため、アプリケーションが苦しんでいた6.6日の稼働時間で再起動前のログが表示されます。

その後、再起動直後にログが表示され、Full GCは5〜10分ごとに発生します。

Full GCが発生しているときに、 jmap -dump:format = b、file = dump.hprof PID を使用して2つのダンプを取得しています(Full GC 2つのFull GCの間)、 http://www.eclipse.org/mat/</でそれらを開いたa>だが、Leak Suspectsには何も役立たなかった:

OutOfMemoryErrorは決して得られないことに注意してください。

私は次にどこを見なければならないのですか?

11
新しいものや捨てられたものがたくさんあります。
追加された 著者 Thorbjørn Ravn Andersen,
収集するものが増えているので、より大きなヒープ上の完全なGCはもっと時間がかかりますが、一般的にもっと多くのスペースが必要な場合は、最大のヒープサイズの大きな値を試してみるとよいでしょう。
追加された 著者 matt b,
@cherouvimあなたが見たことがありますか? oracle.com/technetwork/ java/javase/gc-tuning-6-140523.html ?役に立つかもしれない。
追加された 著者 matt b,
サーバーに16GBのRAMがある場合、なぜ最大ヒープサイズ(-Xmx)を使用しないのですか?
追加された 著者 matt b,
"OutOfMemoryErrorはありません" - メモリが使用されていますが、古い世代がいっぱいであるため完全なGCが発生しているわけではありません。より多くのメモリを割り当てることで、若い世代のオブジェクトが長く保持されます。マイナーなコレクションによって清掃される可能性が高くなります。
追加された 著者 symcbean,
テスト環境で動作を再現できますか?おそらく、いくつかの負荷テストがあります。私は前にこのような振る舞いをデバッグしましたが、通常はプロファイラの助けを借りて(プロダクション環境であなたのサーバーを停止させるでしょう)。
追加された 著者 pcalcao,
@シムビーン:理にかなっている。ヒープを増やして再評価しようとします。
追加された 著者 cherouvim,
@マットb:それはそれを解決しました。私が受け入れることができるように答えとして投稿してください。
追加された 著者 cherouvim,
@スバール:私は一見を持っています。役に立つと思う。ありがとう!
追加された 著者 cherouvim,
@matt b:次回は2GBを試し、何が起こるか見てみましょう。
追加された 著者 cherouvim,
@ pcalcao:私は過去にそうしましたが、一貫していません。 JMeterでのフルスロットルストレステストでは、これは6日に1回、20日にもう1回(!)発生しました。
追加された 著者 cherouvim,
私はOutOfMemoryErrorを一度も持っていないので、アプリケーションが実行できるので、それは大丈夫だと思った。また、私は、JVMにあまりにも多くのメモリを与えるとFull GCが遅くなることを読んだことがあります。本当?
追加された 著者 cherouvim,
eclipse-matは1つのJVMセッションの2つのダンプを比較できます。これは、問題がまだ存在していない状況とフルGCで状況が異なることを示すことができます。
追加された 著者 svaor,

4 答え

私たちがこの問題を抱えたとき、私たちは最終的に若い世代が小さすぎるまで追跡しました。私たちはたくさんのラムを与えていましたが、若い世代には公平な分け合いが与えられていませんでした。

これは、小さなガベージコレクションが頻繁に発生し、いくつかの若いオブジェクトがテニュアされた世代に移動され、より大きなガベージコレクションを意味することを意味しました。

かなり低い値(たとえば2または3)で -XX:NewRatio を使って試してみましょう。

詳細は、こちらをご覧ください。

6
追加された

私は -Xmx1024m から -Xmx2048m に切り替わり、問題は解決しました。今は100日間の稼働時間があります。

4
追加された

あなたのケースで起こっていることは、NewGenライフサイクルよりも少し長く生きているオブジェクトがたくさんあることです。サバイバーのスペースが小さすぎると、OldGenにまっすぐに行きます。 -XX:+ PrintTenuringDistribution はある程度の洞察を提供します。あなたのNewGenは十分に大きいので、 SurvivorRatio を減らしてみてください。

また、jconsoleは、おそらくあなたのメモリで何が起こるかをより視覚的に把握し、試してみてください。

3
追加された

JVMのさまざまなオプションをチューニングする以外にも、新しいバージョンのVMにアップグレードすることをお勧めします。これは、新しいバージョンのガベージコレクタの方がはるかに改善されているからです。

それに加えて、JVMにもっと多くのラムを割り当てるとGCを実行するのに必要な時間が増えることがあると(部分的に)真実なら、16GBのメモリ全体を使用してメモリ占有量を増やすこととの間にトレードオフのポイントがあるので、始めること

Xms1024m -Xmx2048m -XX:PermSize = 256m -XX:MaxPermSize = 512m

よろしく

マッシモ

2
追加された
OK、JVMも更新します。ありがとう。
追加された 著者 cherouvim,
はい、ログには約64MBのPSPermGenが表示されます。これは、JVM、Tomcat、ライブラリ、およびマイアプリの合計ロードされたクラスサイズです。右?
追加された 著者 cherouvim,
私が試してみます。しかし、maxperm 512はあまりにも多すぎませんか? Tomcatインスタンスは約40個の永続(休止状態)エンティティを持つ1つのアプリケーションのみを実行し、Springフレームワークは実行しません。このTomcatでは再デプロイメントは起こりません。シャットダウン/スタートアップだけです。
追加された 著者 cherouvim,
私の提案されたパラメータは単純な推測に過ぎませんでした。試してみると良い点としてJVMを更新することを指摘したいと思います。同様の問題(他の問題もあります)がありました.Javaを27に更新したときに消えてしまいました。最新29ですが、問題がありました。
追加された 著者 user1133275,