ヒープのサイズ変更の問題

デフォルト設定を使用したヒープの操作が、ご使用のアプリケーションで最大のパフォーマンスをもたらさない場合は、これに対処する方法があります。

ほとんどのアプリケーションは、デフォルトの設定により問題なく動作します。 ヒープは定常状態に達するまで拡張され、その状態にとどまります。これにより、ヒープ占有率 (任意の時点におけるヒープ上のライブ・データ量) が 70% になるはずです。 このレベルでは、ガーベッジ・コレクションの頻度と休止時間は許容範囲内であるはずです。

アプリケーションによっては、デフォルト設定の使用が最適な結果をもたらさない場合があります。 ここでは、発生する可能性がある問題と、推奨される対処法を紹介しています。 verbose:gcを使用すると、ヒープのモニターに役立ちます。

ヒープが定常状態に達するまでの、ガーベッジ・コレクションの発生頻度が高すぎる。
verbose:gcを使用して定常状態のヒープのサイズを判別し、-Xmsをこの値に設定します。
ヒープが最大値まで拡張され、占有率が 70% より大きくなる。
-Xmx値を大きくして、ヒープの占有率が70%を超えないようにしてください。 可能な場合は、ページングを防ぐために、最大ヒープ・サイズは物理メモリー内に収まるようにする必要があります。 最大のパフォーマンスを得るには、ヒープのページングが起こらないようにしてください。
70% の占有率における、ガーベッジ・コレクションの発生頻度が高すぎる。
-Xminfの設定を変更します。 デフォルトは 0.3 です。これは、ヒープを拡張することにより、30% のフリー・スペースを維持するということです。 例えばこの値を 0.4 に設定すると、維持するフリー・スペースの目標値が 40% に増大され、ガーベッジ・コレクションの発生頻度が減少されます。
休止時間が長すぎる。
アプリケーションで短期のオブジェクトを多く使用している場合や、トランザクションベース(つまり、トランザクション内のオブジェクトはトランザクションコミット以降も存続しない)の場合、またはヒープ空間が断片化している場合は、-Xgcpolicy:gencongenconがデフォルト)ガベージコレクションポリシーを使用してみてください。 このポリシーは、寿命の短いオブジェクトを寿命の長いオブジェクトとは異なる方法で扱い、休止時間とヒープのフラグメント化を削減できます。
その他の状況では、スループットの低下が許容できる場合は、-Xgcpolicy:optavgpauseポリシーを使用してみてください。 このポリシーにより、ヒープの占有率が上昇した場合の休止時間が短縮され、より安定します。 ただし、スループットがおよそ 5% 低下します。低下する割合は、アプリケーションによって異なります。
ヒープ・サイズが大きいために、グローバル・ガーベッジ・コレクション中に休止時間が許容できない場合は、-Xgcpolicy:balancedを使用してみてください。 バランス・ガーベッジ・コレクション・ポリシーは、多数のクラス・ローダーが作成されており、グローバル・コレクションによるアンロードが必要な場合に頻繁に発生する、クラス・アンロードの問題に対処することもできます。 このポリシーは64 ビット・プラットフォームで使用可能であり、-Xcompressedrefsオプションとともに使用する必要があります。 また、このポリシーは、ヒープ・サイズが 4 GB を超える環境を対象としています。
以下は、役立つヒントです。
  • ヒープのページングが起こらないようにします。つまり、最大ヒープ・サイズが物理メモリー内に納まるようにします。
  • ファイナライザーを回避します。 ファイナライザーが実行されるタイミングを予測することはできず、実行されると多くの場合、問題を引き起こします。 ファイナライザーを使用する場合は、ファイナライザー・メソッド内でオブジェクトを割り振らないようにしてください。 verbose:gcトレースは、ファイナライザーが呼び出されているかどうかを示します。
  • 圧縮を回避します。 verbose:gcトレースは、圧縮が行われているかどうかを示します。 圧縮は通常、大容量のメモリー割り振り要求により引き起こされます。 大容量のメモリー割り振り要求を分析し、可能な場合はこの要求を回避してください。 例えば、大きな配列である場合は、小さな配列に分割してみてください。