web-dev-qa-db-ja.com

Java非常に大きなヒープサイズ

Javaで12 GB以上の非常に大きなヒープを使用した経験はありますか?

  • GCはプログラムを使用不能にしますか?
  • どのGCパラメーターを使用しますか?
  • どのJVM、Sun、またはBEAがこれに適していますか?
  • LinuxまたはWindowsのどちらのプラットフォームが、このような条件下でパフォーマンスが向上しますか?
  • Windowsの場合、64ビットVistaとXPのような高いメモリ負荷の間にパフォーマンスの違いがありますか?
76
pdeva

アプリケーションが対話型ではなく、GCの一時停止が問題にならない場合、64ビットJavaが数百GBでも非常に大きなヒープを処理するのに問題はないはずです。また、WindowsまたはLinuxの安定性の問題に気づいていません。

ただし、GCの一時停止を低く保つ必要がある場合、事態は非常に厄介になります。

  1. デフォルトのスループットであるstop-the-world GCを忘れてください。中程度のヒープ(<〜30 GB)の場合は数十秒間、大きなヒープ(>〜30 GB)の場合は数分間アプリケーションを一時停止します。また、より高速なDIMMを購入しても役に立ちません。

  2. 最善の策は、おそらくCMSコレクターであり、-XX:+ UseConcMarkSweepGCによって有効になります。 CMSガベージコレクターは、最初のマーキングフェーズと再マーキングフェーズでのみアプリケーションを停止します。 4 GB未満のような非常に小さなヒープの場合、これは通常は問題になりませんが、大量のガベージと大きなヒープを作成するアプリケーションの場合、再マーキングフェーズには非常に長い時間がかかる場合があります。 、それでも非常に大きなヒープでは問題になる可能性があります。

  3. CMSガベージコレクタが、終身世代がいっぱいになる前に操作を完了するのに十分な速度でない場合、標準の世界停止GCにフォールバックします。サイズが16 GBのヒープでは、30秒以上の長い一時停止が予想されます。これを回避して、アプリケーションのガベージ生成率を可能な限り低く保つことができます。 CMSは1つのコアのみを使用するため、アプリケーションを実行するコアの数が多いほど、この問題が大きくなることに注意してください。明らかに、CMSがSTWコレクターにフォールバックしないことを保証するnoがあることに注意してください。そして、そうなると、通常はピーク負荷時に発生し、アプリケーションは数秒間停止します。このような構成では、おそらくSLAに署名したくないでしょう。

  4. さて、新しいG1があります。理論的にはCMSの問題を回避するように設計されていますが、試してみて次のことを確認しました。

    • そのスループットはCMSのスループットよりも劣ります。
    • 理論的には、人気のあるメモリブロックを最初に収集しないようにする必要がありますが、ほとんどすべてのブロックが「ポピュラー」である状態にすぐに達し、単純に動作を停止することに基づいているという仮定に達します。
    • 最後に、G1には世界を停止するフォールバックがまだあります。そのコードが実行されることになっている場合は、Oracleに問い合わせてください。彼らが「決して」と言わないなら、なぜコードがあるのか​​、彼らに尋ねてください。したがって、IMHO G1は、実際にJavaのような巨大なヒープ問題を解消するのではなく、(おそらく)少し小さくするだけです。
  5. 大きなメモリを備えた大規模なサーバーに予算がある場合は、Azulが提供するような、優れた商用ハードウェアアクセラレーション、ポーズレスGC技術にもおそらくお金がかかるでしょう。サーバーの1つに384 GB RAMがあり、実際に問題なく動作します。GCで一時停止がなく、世界のストップコードが0行あります。

  6. LinkedInがソーシャルグラフ処理で行ったように、C++で大量のメモリを必要とするアプリケーションのいまいましい部分を記述します。これを行うことですべての問題を回避することはできませんが(ヒープの断片化など)、一時停止を低く保つ方が間違いなく簡単です。

71

私はAzul SystemsのCEOなので、このトピックに関する私の意見には明らかに偏っています! :)それは言われている...

AzulのCTOであるGil Teneには、ガベージコレクションに関連する問題の概要とさまざまな解決策のレビューがあります Javaガベージコレクションとそれについてできること プレゼンテーション、およびこの記事には追加の詳細があります: http://www.infoq.com/articles/azul_gc_in_detail

Zing JVMのAzulのC4ガーベッジコレクターは、並列と同時の両方であり、新世代と旧世代の両方で同じGCメカニズムを使用し、両方の場合で同時に動作して圧縮します。最も重要なことは、C4にはストップワールドフォールバックがないことです。すべての圧縮は、実行中のアプリケーションと同時に実行されます。非常に大規模(数百GBytes)のGC一時停止時間(10ミリ秒未満)を実行しており、アプリケーションによっては1〜2ミリ秒未満の場合があります。

CMSとG1の問題は、ある時点でJavaヒープメモリを圧縮する必要があり、これらのガベージコレクターが両方ともワールド/ STWを停止(つまりアプリケーションを一時停止)して圧縮を実行することです。 AzulのC4は、STWの一時停止を完全に排除するため、Zingには巨大なヒープサイズに対してもGCの一時停止があります。

17
Scott Sellers

12〜16 Gbを割り当てるアプリケーションがありますが、実際には通常の動作中に8〜10にしか達しません。私たちはSun JVMを使用しています(IBMを試してみましたが、ちょっとした災害でしたが、それは私たちにとって無知だったかもしれません... IBMで働いていることを誓う友人がいます)。アプリに余裕を持たせる限り、JVMはGCをあまり多くせずに大きなヒープサイズを処理できます。たくさんの「余分な」メモリが重要です。
Linuxはほとんどの場合Windowsよりも安定しており、安定していない場合、その理由を理解するのは非常に簡単です。 Solarisも同様に堅実であり、DTraceも入手できます:)このような負荷で、なぜVistaまたはXPを使用するのでしょうか?あなたはただトラブルを求めているだけです。 GC paramsについては何も凝ったことはしません。最小割り当てを最大値に等しくなるように設定するので、常にサイズを変更しようとはしませんが、それだけです。

15
Ichorus

LinuxおよびSolarisの2つの異なるアプリケーションで、それぞれ64ビットバージョン(明らかに)Sun 1.6 JVMを使用して、60 GBを超えるヒープサイズを使用しました。

ヒープサイズの制限に近づいた場合を除き、Linuxベースのアプリケーションでガベージコレクションの問題が発生したことはありません。そのシナリオに固有のスラッシング問題(ガベージコレクションの実行に時間がかかりすぎる)を回避するために、プログラム全体でメモリ使用量を最適化し、ピーク使用量が64 GBのヒープサイズ制限を約5〜10%下回るようにしました。

ただし、Solarisで実行されている別のアプリケーションでは、ガベージコレクションの重大な問題が発生したため、多くの調整が必要になりました。これは主に3つのステップで構成されていました。

  1. -XX:+ UseParallelGC -XX:+ UseParallelOldGC JVMオプションによるパラレルガベージコレクターの使用の有効化/強制、および-XX:ParallelGCThreadsオプションによる使用GCスレッド数の制御。詳細については、「 Java SE 6 HotSpot Virtual Machine Garbage Collection Tuning 」を参照してください。

  2. 不要になったローカル変数の「ヌル」への広範囲かつ一見馬鹿げた設定。これらのほとんどは、スコープ外に出た後にガベージコレクションの対象となるはずの変数であり、参照がコピーされないため、メモリリークの状況ではありませんでした。ただし、ガベージコレクションを支援するこの「手持ち」戦略は、問題のSolarisプラットフォームでのこのアプリケーションの何らかの理由で不可解に必要でした。

  3. System.gc()メソッド呼び出しの選択的な使用は、一時的なオブジェクト割り当ての長期間の後、キーコードセクションで呼び出します。これらの呼び出しを使用することに対する標準的な警告と、通常は不要であるという議論を認識していますが、このメモリ集中型アプリケーションを実行するときにガベージコレクションを調整する上で重要であることがわかりました。

上記の3つのステップにより、このアプリケーションを制御しきれなくなり、128 GBのヒープサイズ制限に達するのではなく、約60 GBのヒープ使用量で生産的に実行することが可能になりました。大量のオブジェクトがある場合、メジャーガベージコレクションサイクルは高価であるため、特に並列ガベージコレクタは非常に役立ちました。つまり、メジャーガベージコレクションに必要な時間はヒープ内のオブジェクトの数の関数です。

この規模で他のプラットフォーム固有の問題についてコメントしたり、Sun(Oracle)以外のJVMを使用したことはありません。

9
Joel Hoff

12Gbは、Sunのホットスポットなどの適切なJVM実装では問題ありません。 Sun VMを使用している場合は、Concurrent Mark and Sweepコレクター(-XX:+ UseConcMarkSweepGC)を使用することをお勧めします。

OSがGCのパフォーマンスに大きな影響を与えることはありません。

もちろん、64ビットOSと十分な物理RAMを備えたマシンが必要です。

8
kohlerm

また、ヒープダンプを取得して、アプリのメモリ使用量を改善できる場所を確認し、 Eclipse's MAT などのダンプを分析することをお勧めします。 MATページには、メモリリークの検索の開始に関するいくつかの記事があります。 jmapを使用して、次のようなものでダンプを取得できます。

jmap -heap:format=b pid
5
jlintz

前述のように、非対話型プログラムがある場合は、デフォルトの(コンパクトな)ガベージコレクター(GC)が適切に機能するはずです。対話型プログラムを使用していて、(1)GCが維持できるよりも速くメモリを割り当てない場合、および(2)合計に対して大きすぎる一時オブジェクト(またはオブジェクトのコレクション)を作成しない場合GCが回避するための最大JVMメモリ)、CMSが最適です。

GCに十分なブリージングルームがない対話型プログラムがある場合、問題が発生します。これは、メモリの量に関係なく当てはまりますが、メモリが多いほど悪化します。これは、メモリが少なくなりすぎるとCMSがメモリ不足になり、圧縮GC(G1を含む)がすべてのメモリのガベージチェックが完了するまですべてを一時停止するためです。この世界停止は、メモリが多いほど大きくなります。私を信じてください、あなたのサーブレットを1分以上休止させたくないのです。 G1でこれらの一時停止について詳細なStackOverflowの回答を書きました

それ以来、私の会社はAzul Zingに切り替えました。あなたのアプリが本当にあなたが持っているよりも多くのメモリを必要とする場合には、それはまだ処理できませんが、その瞬間まで、それは夢のように動作します。

しかし、もちろん、Zingは無料ではなく、その特別なソースは特許を取得しています。お金よりも時間がある場合は、JVMのクラスターを使用するようにアプリを書き直してください。

近い将来、Oracleはマルチギガバイトヒープ用の 高性能GCに取り組んでいます。 しかし、今日の時点ではこれは選択肢ではありません。

2
David Leppik

Java 6はあなたを助けることができます: http://Java.Sun.com/developer/technicalArticles/javase/troubleshoot/

1
anjanb

Java Champions http://kirk.blog-city.com/is_your_concurrent_collector_failing_you.htm のいずれかからgcについての記事があります。

カーク、著者は「GCログを送ってください

現在、Sun JVMで生成されたGCログの調査に興味があります。これらのログにはビジネス関連の情報が含まれていないため、専有情報の保護に関する懸念事項を緩和する必要があります。ログを使用して、OS、JREの完全なバージョン情報、および設定したヒープ/ gc関連のコマンドラインスイッチについて言及するようお願いします。また、Grails/Groovey、JRuby、ScalaまたはJava以外の、またはJava以外の何かを実行しているかどうかを知りたいです。最適な設定は-Xloggc:です。 OSのサイズ制限に達してもロールオーバーしません。何かおもしろいものが見つかったら、すぐに簡単な概要をお伝えします。

1
anjanb

数年前、私はJRockitとSun JVMを12Gヒープで比較しました。 JRockitが勝ち、Linux hugepagesのサポートによりテスト実行が20%速くなりました。テストとしてのYMMVは、プロセッサ/メモリを集中的に使用し、主にシングルスレッドでした。

1
ShabbyDoo

64ビットに切り替えると、より多くのメモリが使用されます。ポインターは4ではなく8バイトになります。多数のオブジェクトを作成している場合、すべてのオブジェクトが参照(ポインター)であるため、これは顕著です。

私は最近、問題なくSun 1.6 JVMを使用してJavaで15GBのメモリを割り当てました。それはすべて一度だけ割り当てられます。 Linuxでも、Sun JVMは64ビットWindowsでも同じように動作すると思います。

1
Chris de Vries

アプリに対してvisualgcを実行してみてください。 http://Java.Sun.com/performance/jvmstat/ のjvmstatダウンロードの一部であるヒープ視覚化ツール

GCログを読むよりもずっと簡単です。

ヒープの一部(世代)がどのように機能しているかをすぐに理解できます。合計ヒープは10GBですが、ヒープのさまざまな部分ははるかに小さくなります。ヒープのEden部分のGCは比較的安価ですが、古い世代のフルGCは高価です。エデンが大きく、古い世代がほとんど触れられないようにヒープのサイズを調整することは、優れた戦略です。これは非常に大きな全体的なヒープをもたらす可能性がありますが、JVMがページに触れない場合、それは単なる仮想ページであり、RAMを占有する必要はありません。

1
tpgould

Sunにはしばらくの間、itanium 64ビットjvmがありましたが、itaniumは人気のある目的地ではありません。 solarisおよびlinux 64ビットJVMは、後を追うべきものです。
いくつかの質問

1)アプリケーションは安定していますか?
2)32ビットJVMでアプリを既にテストしましたか?
3)同じボックスで複数のJVMを実行しても大丈夫ですか?

Windowsの64ビットOSが約1年ほどで安定することを期待していますが、それまでは、solaris/linuxの方が良いかもしれません。

0
anjanb

XPがアドレス指定できる最大メモリは4ギガです( here )。そのため、XPを使用したくない場合があります(64ビットOSを使用)。

0
Milhous