5

JVMの適切な設定を取得するのに苦労しています。

ユースケースは次のとおりです。Tomcatはリクエストを処理しています(300req / s)。ただし、これらは非常に高速(Key-Valueルックアップ)であるため、パフォーマンスの問題はありません。3時間ごとに提供されているデータを更新する必要があるまで、すべてが正常に機能します。あなたは私が大きなHashMapを持っていて、ルックアップをしているだけだと想像することができます。データのリロード中に一時的なHashMapを作成し、それを交換します。かなりの量のデータをロードする必要があります(毎回メモリに最大800MB)。

私が抱えている問題は、これらのロード中に時々Tomcatが応答を停止することです。当初の問題はプロモーションの失敗とFullGCでしたが、設定を調整することでこれらの問題を回避しました。

お気づきかもしれませんが、CMSコレクターが起動したときに、すでに値を下げています。プロモーションの失敗などはもう発生しません。若い世代は、マイナーコレクションを高速化するために適度に小さいです。すべてのリクエストオブジェクトが若くして消滅し、昇格されないものは自動的に古い世代にプロモートされるため、SurvivorRatioを増やしました(データが読み込まれています)。

しかし、データのロード中にTomcatで503エラーが発生します。gc.logでは、このプロセス中にマイナーコレクションが遅くなり始めました。ミリ秒と比較して、秒単位になりました。ロードプロセスを遅くしてGCに息抜きを与えようとしましたが、うまくいかないようです...この問題は、古い世代の容量に達した瞬間に特に問題になります。CMSが起動し、メモリを解放すると、後で割り当てがかなり遅くなります。gc.logにエラーは表示されなくなりました。何が違うのですか?断片化が問題になる可能性があることは知っていますが、プロモーションが失敗することはありません。マシンは8コアサーバーです。GCThreadの数を減らすことは意味がありますか?データ読み込みスレッドに低いスレッド優先度を設定することは意味がありますか?

バックグラウンドで定期的にCMSコレクターを開始する方法はありますか?スワップされているデータは、実際にはすぐにガベージコレクションされる可能性があります。

私はどんな提案にもオープンです!

これが私のJVM設定です。

-Xms14g
-Xmx14g
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+AlwaysPreTouch 
-XX:MaxNewSize=256m
-XX:NewSize=256m 
-XX:MaxPermSize=128m 
-XX:PermSize=128m 
-XX:SurvivorRatio=24 
-XX:+UseCMSInitiatingOccupancyOnly 
-XX:CMSInitiatingOccupancyFraction=88 
-XX:+UseCompressedStrings 
-XX:+DisableExplicitGC 

JDK 1.6.33 Tomcat 6

gc.logスニペット:

7行目データの読み込みが開始されます

20行目停止します

http://safebin.net/9124

4

2 に答える 2

2

その添付されたログを見て、マイナーなGC時間のこれらの大幅な増加を見ると、マシンがJVM以外のプロセスからの非常に重い負荷にさらされていると私は信じています。

これについての私の推論は、マイナーGCが実行されているときに、すべてのアプリケーションスレッドが停止するということです。したがって、新しい世代のサイズが一定であることを確認すると、アプリケーションがマイナーGC時間に影響を与えることはできません。

ただし、この間にマシン上の他のプロセスからの負荷が多い場合、GCスレッドは実行時間を競い合い、この動作を確認できます。

データロードの実行中に他のプロセスのCPU使用率を確認できますか?

編集:ログをもう少し見てみると、別の考えられる説明が思い浮かびます。

ターゲットのサバイバースペースがいっぱいになっているようです(ParNewは「遅い」GCごとに正確に10048Kになります)。これは、オブジェクトが直接古い世代にプロモートされることを意味し、これにより速度が低下する可能性があります。新世代の規模を拡大し、生存率を下げようと思います。新しい世代サイズや生存率をまったく設定せずに実行して、JVMがこれをどのように最適化したかを確認することもできます(ただし、JVMは通常、このようなバーストを最適化するための不十分な仕事をすることに注意してください)。

于 2012-12-11T19:50:56.740 に答える
1

負荷は約90秒間続き、1秒ごとにGCによって中断されますが、定常状態の占有率が約5G(周囲のログラインが定常状態であると仮定)の14Gヒープがあります。これは、大量のメモリが使用されていることを意味します。無駄に。前の答えは、生存者のスペースが小さすぎると言っている場合、(提示されたデータに基づいて)正しいように見えると思います。残りの時間をルックアップする以外に何もしないのが合理的である場合、完全に合理的な戦略は次のようになります。

  • 保有しきい値=0(または1)
  • edenサイズ>ワーキングセットの2倍なので、おそらく1.5〜2G(つまり、現在のライブデータと作業コピーを完全にedenに常駐させる)
  • 保有=残っているものは何でも

ここでのポイントは、ロードフェーズ中に若いコレクションを完全に回避することです。ただし、テニュアのしきい値が0の場合は、前のバージョンがテニュアになっている可能性が高く、最終的には、それをクリーンアップするための長いコレクションが表示される可能性があります。もう1つのオプションは、逆の方法で、データの2〜3バージョンに適合するのに十分な大きさのテニュアを持ち、若いコレクションの頻度を最小限に抑え、テニュアをできるだけ早く収集できるようにするために、残りを編集することです。 。

何が最も効果的に機能するかは、アプリが残りの時間に他に何をしているかによって異なります。

大きなヒープの場合、cmsトリガーはかなり高いように見えますが、88%で収集を開始した場合、fullgcが強制される前にジョブを終了する時間はありますか?ほとんどの場合、実際にほとんど割り当てを行っていない場合は、かなり安全だと思います。

于 2012-12-11T21:30:54.757 に答える