ガベージコレクタのエルゴノミクス

J2SE 5.0 では、以下の変更が実施されています。
  1. サーバ VM を実行しているサーバクラスマシンでは、ガベージコレクタ (GC) が、これまでのシリアルコレクタ (-XX:+UseSerialGC) からパラレルコレクタ (-XX:+UseParallelGC) に変更されました。このデフォルトは、-XX:+UseSerialGC コマンド行オプションを使用して java コマンドにオーバーライドできます。

  2. パラレルガベージコレクタ (-XX:+UseParallelGC) を使用してどちらかの VM (クライアントかサーバ) を実行するサーバクラスマシンでは、初期ヒープサイズと最大ヒープサイズが以下のように変更されました。

    初期ヒープサイズ:

    マシンの物理メモリの 1/64 か、妥当な最小サイズかの大きい方。J2SE 5.0 より前は、デフォルトの初期ヒープサイズは妥当な最小サイズで、プラットフォームごとに異なっていた。このデフォルトは、-Xms コマンド行オプションを使用してオーバーライドが可能

    最大ヒープサイズ:

    物理メモリの 1/4 か、1GB かの小さい方。J2SE 5.0 より前のデフォルトの最大ヒープサイズは 64MB。このデフォルトは、-Xmx コマンド行オプションを使用してオーバーライドが可能


    注: ヒープサイズに対して与えられた境界と分数は、J2SE 5.0 に対して適切です。これは、コンピュータがより高性能になるにつれ、今後のリリースで変更される可能性があります。


  3. パラレルガベージコレクタ (UseParallelGC) は、少量のヒープのコレクションに時間がかかりすぎると、メモリ不足の例外をスローします。ヒープサイズを大きくすると、この例外を回避できます。パラメータの -XX:GCTimeLimit=time-limit および -XX:GCHeapFreeLimit=space-limit を設定することもできます。time-limit と space-limit はそれぞれ以下の内容を表します。

    time-limit:
    ガベージコレクションに要する時間の上限を、合計時間に対する割合で示す (デフォルトは 98)
    space-limit:
    ガベージコレクション間に解放されるスペース量の下限を、最大ヒープに対する割合で示す (デフォルトは 2)

  4. -XX:+UseParallelGC ガベージコレクタと共にデフォルトで使用される -XX:+UseAdaptiveSizePolicy の実装が、以下の 3 つの目標を考慮して変更されました。

実装では以下のことを (この順序で) チェックします。

    1. GC の一時停止時間が一時停止目標よりも長い場合は、世代サイズを小さくして目標を達成する
    2. 一時停止目標を達成した場合は、アプリケーションのスループット目標を検討する。アプリケーションのスループット目標を達成しない場合は、世代サイズを大きくして目標を達成する
    3. 一時停止目標とスループット目標の両方を達成した場合は、世代サイズを小さくして占有スペースを減らす

フラグ

    -XX:MaxGCPauseMillis=nnn
    仮想マシンの場合、一時停止時間として望ましいのは、nnn ミリ秒以下です。VM は、GC により生じた一時停止を nnn ミリ秒よりも短く維持できるように、Java のヒープサイズおよびほかの GC に関連するパラメータを調整します。これにより VM の全体のスループットが下がる可能性があり、場合によっては、VM が目的の一時停止時間目標を達成できない場合があります。

    デフォルトでは、一時停止時間目標はありません。一時停止時間の目標がどの程度まで達成できるかについては明確な制限があります。GC の一時停止時間は、ヒープ内のライブデータの量により異なります。コレクションの大小は、様々な面でライブデータの量に依存します。このパラメータは注意して扱う必要があります。値が小さすぎると、システムがガベージコレクションに余分な時間を使ってしまいます。

    -XX:GCTimeRatio=nnn
    仮想マシンの場合、望ましい値は、コレクタで要するアプリケーションの実行時間の 1 / (1 + nnn) 以下です。

    たとえば、-XX:GCTimeRatio=19 が、GC の合計時間の 5% と 95% のスループットを目標に設定したとします。つまり、アプリケーションでは、コレクタの 19 倍の時間が必要ということになります。

    デフォルト値は 99 で、アプリケーションがコレクタの少なくとも 99 倍の時間を必要とするということです。つまり、コレクタは多くても合計時間の 1% で実行されることになります。サーバアプリケーションの場合、これは良い選択といえます。値が高すぎると、ヒープサイズがその最大値にまで達する可能性があります。

推奨案

ヒープがデフォルトの最大ヒープサイズよりも大きいことが分からない場合は、ヒープに最大値を設定しないようにします。アプリケーションに対して十分なスループット目標を設定します。

理想的な状況では、ヒープは選択したスループット目標をサポートする値 (最大値未満) にまで増えます。

ヒープが最大値まで増えた場合、スループットはその最大値内では達成できないということになります。最大ヒープはできるだけ大きくしますが、プラットフォームの物理メモリよりも大きくならないように設定して、もう一度アプリケーションを実行します。それでもスループット目標が達成できない場合は、プラットフォームで使用可能なメモリに対して目標が高すぎることになります。

スループットは達成できるものの、一時停止が長すぎる場合は、一時停止時間目標を選択します。この場合、スループット目標が達成できない可能性があるため、アプリケーションにとって妥協点となる値を選択します。