初期ヒープ・サイズおよび最大ヒープ・サイズ

ガーベッジ・コレクター (GC) の操作を理解することは、ヒープを効率的に管理するための初期ヒープ・サイズと最大ヒープ・サイズの設定に役立ちます。

ガーベッジ・コレクターは、以下の理由によりヒープ・サイズの占有率を 40% から 70% までに保つようにヒープ・サイズを変更します。
  • ヒープ占有率が 70% を超えると、GC サイクルが増えます。 それにより、パフォーマンスが低下する可能性があります。 この動作は、-Xminfオプションを設定することによって変更できます。
  • ヒープ占有率が 40% を下回ると、GC サイクルが減ります。 ただし、そのようなサイクルは必要以上に時間がかかります。 それに伴い、休止時間も長くなります。 その結果、パフォーマンスが低下する可能性があります。 この動作は、-Xmaxfオプションを設定することによって変更できます。
初期ヒープ・サイズや最大ヒープ・サイズを設定しないと、GC が必要に応じてヒープを拡大/縮小します。 ただし、 -Xms オプションと -Xmx オプションを使用してヒープ・サイズを修正した場合、GC によって Java™ ヒープが拡張または縮小されることはありません。 アプリケーションのパフォーマンスを最適化して、ヒープ占有率を 40% から 70% までの範囲内で維持するには、結果として最大ヒープ・サイズ設定をアプリケーションの最大ヒープ占有率より 43% 以上大きくする必要があります。 例えば、アプリケーションの最大ヒープ占有率が 70 MB の場合は、以下の計算で示されるように、 最大ヒープ・サイズとして 100 MB を設定する必要があります。
70 + (70 * 43/100)

通常、最小ヒープ・サイズと最大ヒープ・サイズを同じ値に設定することはお勧めしません。 ヒープがフルになるまでガーベッジ・コレクションが先延ばしされるためです。 そのため GC の初回実行時に、プロセスの所要時間が長くなります。 また、ヒープが断片化され、ヒープの圧縮が必要となる確率が高まります。 アプリケーションで必要とされる最小ヒープ・サイズでアプリケーションを開始してください。 これにより、GC が開始された場合に、ヒープが小さいために、頻繁に効率よく実行されるようになります。

GC により十分な量のガーベッジを検出できない場合、圧縮が実行されます。 GC によって十分なガーベッジが検出された場合、またはヒープ拡張の他の条件のいずれかが満たされた場合 ( OpenJ9 ユーザー資料の「 ヒープ割り振り 」を参照)、GC によってヒープが拡張されます。

そのため、アプリケーションは通常、ヒープがいっぱいになるまで実行されます。 続けて、連続するガーベッジ・コレクション・サイクルにより、ガーベッジが復旧されます。 ヒープがライブ・オブジェクトでいっぱいになると、GC によりヒープの圧縮が行われます。 必要な量のガーベッジが復旧されていない場合は、GC によりヒープの拡張が行われます。

前述のとおり、アプリケーションの要求が高まると、GC によりヒープの圧縮が行われるため、ヒープは、元のヒープの下部にオブジェクトのセットが圧縮された状態で拡張されます。 圧縮は、圧縮が必要であることが分かった時点で最小のヒープ・サイズに対して実行されるため、このプロセスはヒープの効率的な管理方法です。 ヒープが増大すると、最小ヒープ・サイズにより圧縮が実行されます。 アプリケーションに最初に含まれるオブジェクトが、キー・セットまたはルート・セットとなることが多いため、そのようなオブジェクトを早期に圧縮すると、より寿命の短いオブジェクトに残りのヒープが解放される、という事例もあります。

最終的に JVM には、ヒープの下部に寿命の長いオブジェクトすべてが圧縮された、最大サイズのヒープが含まれます。 圧縮は、圧縮を行うことによる負荷が最も低いフェーズで行われました。 ヒープの拡張に必要な処理量およびメモリー使用量は、非常に大きな断片化されたヒープを収集して圧縮する場合のコストに比べ、ごくわずかです。