46

保険料率の計算に使用される Web アプリケーションのパフォーマンスの問題に対処するためのミーティングがありました。計算は C/C++ モジュールに実装されており、他のソフトウェア パッケージでも使用されています。Web サービスとして利用できるようにするために、XML ベースのインターフェースを公開し、JNI を介して C/C++ モジュールを呼び出す Java ラッパーが実装されました。

測定では、Java 部分内の各計算に数秒が費やされたことが示されました。したがって、私の最初の推奨事項は、VM でガベージ コレクションのログ記録を有効にすることでした。ストップ・ザ・ワールドのフル GC が多数作成されていることがすぐにわかりました。それについて話すと、Java部分の開発者は、System.gc()「使用後にメモリが確実に解放されるようにするために」何度か行ったと語っています。

OK、その声明についてはこれ以上詳しく説明しません... ;-)

次に、上記-XX:+DisableExplicitGCの VM 引数も追加し、テストを再実行しました。これにより、計算ごとに約 5 秒短縮されました。

System.gc()リリース プロセスのこの時点で、これらの呼び出しをすべて削除してコードを変更することはできないため-XX:+DisableExplicitGC、新しい Jar が作成されるまで、本番環境に追加することを考えています。

ここで問題は、そうすることでリスクが生じる可能性があるかどうかです。私が考えることができる唯一のことはSystem.gc()、再デプロイ時に内部的に使用する tomcat ですが、それは単なる推測です。前方に他の危険はありますか?

4

3 に答える 3

43

-XX:+DisableExplicitGCフラグを設定してストップ・ザ・ワールド GC イベントを修正しているのはあなただけではありません。残念なことに (ドキュメントに免責事項が記載されているにもかかわらず)、多くの開発者は、JVM よりもメモリーを収集するタイミングをよく知っていると判断し、まさにこのタイプの問題を引き起こします。

実稼働環境が改善された多くの事例と、-XX:+DisableExplicitGCマイナスの副作用があった事例はゼロであることを認識しています。

安全な方法は、ストレス テスト環境でそのフラグを設定して、現在の運用コードを負荷の下で実行し、通常の QA サイクルを実行することです。

それができない場合は、フラグを設定するリスクは、ほとんどの場合、設定しない場合のコストよりも小さいことをお勧めします。

于 2012-10-11T19:42:35.997 に答える
2

私はこれと同じ問題に取り組んできました.私が見つけたすべての情報に基づいて、そこには間違いなく何らかのリスクがあるようです. @millimoose からの元の投稿へのコメントとhttps://bugs.openjdk.java.net/browse/JDK-6200079によると、NIO が直接バッファーが使用されています。これらは、私たちが使用している Websphere 8.5 アプリ サーバーの内部実装で使用されているようです。これをデバッグ中にキャプチャできたスタック トレースは次のとおりです。

3XMTHREADINFO      "WebContainer : 25" J9VMThread:0x0000000006FC5D00, j9thread_t:0x00007F60E41753E0, java/lang/Thread:0x000000060B735590, state:R, prio=5
3XMJAVALTHREAD            (java/lang/Thread getId:0xFE, isDaemon:true)
3XMTHREADINFO1            (native thread ID:0x1039, native priority:0x5, native policy:UNKNOWN)
3XMTHREADINFO2            (native stack address range from:0x00007F6067621000, to:0x00007F6067662000, size:0x41000)
3XMCPUTIME               CPU usage total: 80.222215853 secs
3XMHEAPALLOC             Heap bytes allocated since last GC cycle=1594568 (0x1854C8)
3XMTHREADINFO3           Java callstack:
4XESTACKTRACE                at java/lang/System.gc(System.java:329)
4XESTACKTRACE                at java/nio/Bits.syncReserveMemory(Bits.java:721)
5XESTACKTRACE                   (entered lock: java/nio/Bits@0x000000060000B690, entry count: 1)
4XESTACKTRACE                at java/nio/Bits.reserveMemory(Bits.java:766(Compiled Code))
4XESTACKTRACE                at java/nio/DirectByteBuffer.<init>(DirectByteBuffer.java:123(Compiled Code))
4XESTACKTRACE                at java/nio/ByteBuffer.allocateDirect(ByteBuffer.java:306(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/buffermgmt/impl/WsByteBufferPoolManagerImpl.allocateBufferDirect(WsByteBufferPoolManagerImpl.java:706(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/buffermgmt/impl/WsByteBufferPoolManagerImpl.allocateCommon(WsByteBufferPoolManagerImpl.java:612(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/buffermgmt/impl/WsByteBufferPoolManagerImpl.allocateDirect(WsByteBufferPoolManagerImpl.java:527(Compiled Code))
4XESTACKTRACE                at com/ibm/io/async/ResultHandler.runEventProcessingLoop(ResultHandler.java:507(Compiled Code))
4XESTACKTRACE                at com/ibm/io/async/ResultHandler$2.run(ResultHandler.java:905(Compiled Code))
4XESTACKTRACE                at com/ibm/ws/util/ThreadPool$Worker.run(ThreadPool.java:1864(Compiled Code))
3XMTHREADINFO3           Native callstack:
4XENATIVESTACK               (0x00007F61083DD122 [libj9prt26.so+0x13122])
4XENATIVESTACK               (0x00007F61083EA79F [libj9prt26.so+0x2079f])
....

NIOダイレクトバイトバッファが使用されているときに -XX:+DisableExplicitGC を設定することの完全な影響が正確に何であるかはまだ完全には明らかではありません(これによりメモリリークが発生しますか?)が、少なくともいくつかのリスクがあるように見えますそこの。Websphere 以外のアプリ サーバーを使用している場合は、無効にする前に、アプリ サーバー自体が NIO 経由で System.gc() を呼び出していないことを確認することをお勧めします。ここで、NIO ライブラリへの正確な影響について明確にすることを願っている関連する質問があります: Impact of setting -XX:+DisableExplicitGC when NIO direct buffers are used

ちなみに、Websphere は起動プロセス中に手動で System.gc() を数回呼び出すようです。通常、アプリ サーバーが起動されてから最初の数秒以内に 2 回、最初の 1 ~ 2 分以内に 3 回目です (おそらくアプリケーションが起動したとき)。配備されています)。私たちの場合、これが最初に調査を開始した理由です。System.gc() 呼び出しはすべて、アプリケーション コードからではなく、アプリ サーバーから直接行われているようです。

また、NIO ライブラリに加えて、RMI 分散ガベージ コレクションの JDK 内部実装もSystem.gc() を呼び出す ことに注意してください。 API

-XX:+DisableExplicitGC を有効にすると、RMI DGC にも大混乱が生じるかどうかは、私には少しわかりません。私が見つけることができた唯一の参照は、これに対処することでさえ、上記の最初の参照であり、

「ただし、ほとんどの場合、効果的な DGC には通常の GC アクティビティで十分です」

その「ほとんどの場合」の修飾子は、私には非常に希望に満ちたものに聞こえるので、繰り返しになりますが、すべての System.gc() 呼び出しを停止するだけで、少なくともいくつかのリスクがあるようです。可能であればコードを作成し、最後の手段として完全にオフにするだけです。

于 2015-10-02T16:51:30.600 に答える
1

-XX:+DisableExplicitGC CMS を使用している場合は-XX:+CMSClassUnloadingEnabled、GC がいっぱいになる別の理由 (つまり、PermGen がいっぱい) を制限するためにも使用したい場合があります。それ以外は、オプションの使用に問題はありませんでしたが-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses、明示的な GC の唯一の原因はアプリケーション コードではなく RMI であったため、 の使用に切り替えました。

于 2012-10-11T19:50:26.890 に答える