22

これは、「Java ガベージ コレクタを強制的に実行する方法を教えてください」という別の質問です。私たちのアプリケーションでは、これを行う正当な理由があると信じています。

これは、通常約 5M のライブ オブジェクトを持つサーバー アプリケーションです。5 分ごとに 1 回、約 60 秒かかる分析タスクを実行します。分析の実行中にフル GC がトリガーされると、約 40M のライブ オブジェクトが存在します。余分な 35M オブジェクトは、分析が完了するとガベージになります。サーバーは常に (分析の実行中であっても) 要求に応答し続ける必要があります。

分析が実行されていないときに呼び出された場合、完全な GC は約 1.5 秒かかりますが、分析が実行されている間は約 15 秒かかります。残念ながら、私たちの割り当てパターンは、分析が 20% の時間しか実行されていないにもかかわらず、分析中にフル GC が通常トリガーされるようなものです。(3 回または 4 回の分析実行ごとにフル GC がトリガーされます。)

古い世代の空き容量が特定のしきい値 (5GB) を下回った場合に、分析実行を開始する直前に、非常に軽蔑されている System.gc() を呼び出すコードを追加しました。この利点は非常に大きなものでした。15 秒の一時停止時間ではなく 1.5 秒の一時停止時間が得られ、より多くのゴ​​ミを掘り出し物に解放できます。ただし、System.gc() 呼び出しが無視される場合があり、GC が自動的にトリガーされる数分後に 15 秒の一時停止が発生します。

それでは私の質問: ガベージ コレクターを実行するようにもっと強く説得するためにできることはありますか? 1.7.0_09-icedtea を実行し、Parallel GC を使用しています。(a) ガベージ コレクションを手動で強制する信頼できる方法、または (b) よりインテリジェントな自動決定を行うようにコレクターを調整する方法のいずれかが必要です。(b) ワーキング セットがこのように劇的に変化することをコレクターがどのように検出できるかがはっきりしないため、難しいように思えます。

必要に応じて、かなりのハッカーに頼るつもりです。これは私たちにとって深刻な問題です。(代わりに CMS や G1 コンパクターを検討するかもしれませんが、私は CMS のスループットへの影響に懐疑的です。また、G1 は、私たちが使用する大きなバイト配列に対して動作が悪いと評判です。)

補遺: 本番環境では、これまでの経験から、 System.gc()は通常、完全なガベージ コレクションをトリガーします。少なくとも、私たちがそれを呼んでいる状況では。(10 ~ 30 分ごとに 1 回だけ呼び出すだけで、ヒープはある程度ガベージでいっぱいではありません。) ガベージ コレクションをより確実にトリガーできると便利ですが、ほとんどの場合は役に立ちます。

4

4 に答える 4

6

問題は、要件とメモリ プロファイルがまったく異なる 2 つのアプリケーションを同じ JVM で実行していることです。

ユーザーに面したサーバーが常に応答し続けるように、ユーザーに面していないプロセスでデータ分析を個別に実行します。定期的な分析により、何らかの要約または結果データが生成されると思います。それをユーザー向けサーバーに送信してそこから提供できるようにするか、フロントエンドで分析サーバーとは別に取得できるようにします。

于 2013-10-17T01:05:56.653 に答える
1

あなたの質問に直接答えるのではなく (私にはできません)、可能な代替案を提供したいと思います。

分析の実行中に多数の大きなバイト配列を割り当て、実行の最後にガベージ コレクションを許可している (または次の実行の直前にガベージ コレクションを強制しようとしている) ようです。

代わりに、可能であれば、バイト配列の独自のプールを管理してみてください。これにより、最良の場合、アプリケーションの最初の起動時に必要なすべての配列を 1 回割り当てると、アプリケーションの存続期間中存続し、ガベージコレクションする必要はありません。

もちろん、この考え方は、より複雑なデータ構造とオブジェクト インスタンスに拡張できます。

これはすべて、必要なときにメモリを割り当て、不要なときにメモリを「解放」するよりもかなり多くの作業ですが、ガベージ コレクタが実行する必要がある作業を大幅に削減する必要があります。

于 2013-10-17T00:57:16.853 に答える