6 パラレル・コレクタ
パラレル・コレクタ(ここではスループット・コレクタとも呼ばれる)は、シリアル・コレクタと同様に世代別コレクタです。シリアル・コレクタとパラレル・コレクタとの主な違いは、パラレル・コレクタには複数のスレッドがあり、これを使用してガベージ・コレクションを高速化する点です。
パラレル・コレクタを有効にするには、コマンド行オプション-XX:+UseParallelGC
を使用します。デフォルトで、このオプションを使用すると、マイナー・コレクションもメジャー・コレクションも並列実行して、ガベージ・コレクションのオーバーヘッドをさらに削減します。
パラレル・コレクタのガベージ・コレクタのスレッド数
パラレル・コレクタでは、<N>個( <N>は9以上)のハードウェア・スレッドを使用するマシン上で、 <N>の固定比率をガベージ・コレクタのスレッド数として使用します。
<N>の値が大きい場合、この比率は約5/8です。 <N>の値が8未満の場合、使用される数値は<N>です。特定のプラットフォームでは、比率は5/16に低下します。指定のガベージ・コレクタ・スレッド数はコマンド行オプション(後述)を使用して調整できます。プロセッサが1個のホストでは、並列実行にオーバーヘッド(同期化など)が必要になるため、パラレル・コレクタはシリアル・コレクタよりもパフォーマンスが低くなる可能性があります。ただし、中規模から大規模なヒープを使用してアプリケーションを実行する場合は、2個のプロセッサを搭載したコンピュータではシリアル・コレクタよりもパフォーマンスが若干向上し、プロセッサが3個以上利用可能場合はシリアル・コレクタよりも大幅にパフォーマンスが向上するのが一般的です。
ガベージ・コレクタのスレッド数は、コマンド行オプション-XX:ParallelGCThreads=
<N>で制御できます。コマンド行オプションを使用してヒープの調整を行う場合、パラレル・コレクタで高いパフォーマンスを実現するために必要なヒープ・サイズは、シリアル・コレクタで必要なヒープ・サイズと同じです。ただし、パラレル・コレクタは、コレクションによる一時停止を短縮する目的でのみ有効にしてください。マイナー・コレクションでは複数のガベージ・コレクタ・スレッドが使用されているため、コレクション時の若い世代から古い世代への昇格に伴い断片化が発生する可能性があるからです。マイナー・コレクションで使用されている各ガベージ・コレクション・スレッドは昇格のために古い世代の一部を確保し、その使用可能な領域が「昇格バッファ」に分割されるために、断片化の影響を受ける可能性があります。ガベージ・コレクタ・スレッドの数を減らし、古い世代のサイズを増やすことによって、この断片化の影響は低減します。
パラレル・コレクタ・エルゴノミクス
-XX:+UseParallelGC
を使用してパラレル・コレクタを選択する場合、自動調整の方法を有効にしているので、ユーザーは世代サイズや他の低レベルのチューニング詳細ではなく、動作を指定できます。
パラレル・コレクタの動作を指定するオプション
ガベージ・コレクションの最大一時停止時間、スループットおよびフットプリント(ヒープ・サイズ)を指定できます。
-
ガベージ・コレクションの最大一時停止時間: 最大一時停止時間目標は、コマンド行オプション
-XX:MaxGCPauseMillis=
<N>で指定します。これは、<N>ミリ秒以下の一時停止時間が望ましいというヒントとして解釈されます。デフォルトでは、最大一時停止時間目標はありません。一時停止時間目標が指定されている場合、ガベージ・コレクションによる一時停止を指定された値以内に維持するよう、ヒープ・サイズとその他のガベージ・コレクション関連パラメータが調整されます。ただし、必要な一時停止時間目標が常に満たされるとはかぎりません。このような調整により、ガベージ・コレクタではアプリケーションの全体的なスループットが低下する可能性があります。 -
スループット: スループット目標は、ガベージ・コレクションの実行に消費された時間とガベージ・コレクション以外で消費された時間(アプリケーション時間と呼ばれる)の観点から測定されます。この目標はコマンド行オプション
-XX:GCTimeRatio=
<N>で指定され、ガベージ・コレクション時間のアプリケーション時間に対する比率を1 / (1 +
<N>)
に設定します。たとえば、
-XX:GCTimeRatio=19
は、ガベージ・コレクションに合計時間の20分の1 (5%)という目標を設定します。デフォルト値は99で、ガベージ・コレクションに1%という時間の目標を設定します。 -
フットプリント: ヒープの最大フットプリントはオプション
-Xmx
<N>を使用して指定します。また、コレクタには、他の目標が満たされている場合はヒープ・サイズを最小化するという暗黙の目標があります。
パラレル・コレクタの目標の優先度
目標は最大一時停止時間目標、スループット目標、最小フットプリント目標で、この順に対処されます。
最大一時停止時間目標を最初に満たします。これを満たした上で、スループット目標に対処します。同様に、先の2つの目標を満たした上で、フットプリント目標を検討します。
パラレル・コレクタの世代サイズの調整
コレクタが保持する平均一時停止時間などの統計は、各コレクションの終了時に更新されます。
その後で、目標を満たしているか確認するためのテストと、必要に応じて世代サイズの調整が行われます。例外として、明示的なガベージ・コレクション(System.gc()の呼出し)は、世代サイズの統計保持や調整上、無視されます。
世代サイズの拡大と縮小は、適切なサイズになるまで段階的に増減されるように、世代サイズの一定割合を単位として徐々に調整されます。拡大と縮小はそれぞれ別の比率で行われます。デフォルトで、世代の拡大率は20%、縮小率は5%です。拡大率はコマンド行オプション-XX:YoungGenerationSizeIncrement=
<Y> (若い世代の場合)および-XX:TenuredGenerationSizeIncrement=
<T> (古い世代の場合)で制御します。世代の縮小率はコマンド行フラグ-XX:AdaptiveSizeDecrementScaleFactor=
<D>で調整します。拡大率がX%の場合、縮小率はX/D%になります。
コレクタの起動時に世代の拡大が決定されると、増加率が割り増しされます。この割増しはコレクションの回数に伴って減衰し、長期的な影響はありません。割増しの目的は、起動時のパフォーマンスを向上させることです。縮小率に割増しはありません。
最大一時停止時間目標が満たされていない場合、一度に縮小できるのは1つの世代のサイズのみです。2つの世代の一時停止時間が目標を超えている場合、一時停止時間が大きい方の世代のサイズが先に縮小されます。
スループット目標が満たされていない場合は、両方の世代サイズが増加されます。どちらも、ガベージ・コレクション合計時間に占めるそれぞれの割合に比例して増加されます。たとえば、若い世代のガベージ・コレクション時間が合計コレクション時間の25%であり、若い世代の完全な拡大率が20%単位である場合、若い世代は5%単位で増加することになります。
パラレル・コレクタのデフォルト・ヒープ・サイズ
コマンド行で初期ヒープ・サイズと最大ヒープ・サイズが指定されていない場合、これらのサイズはマシン上のメモリー容量に基づいて計算されます。初期ヒープ・サイズは物理メモリーの1/64ですが、デフォルトの最大ヒープ・サイズは物理メモリーの1/4です。若い世代に割り当てられる最大領域サイズは、全ヒープ・サイズの1/3です。
パラレル・コレクタのヒープ・サイズの初期値と最大値の指定
オプション-Xms
(初期ヒープ・サイズ)および-Xmx
(最大ヒープ・サイズ)を使用して、初期および最大のヒープ・サイズを指定できます。
アプリケーションがうまく動作するために必要なヒープ領域がわかっている場合は、-Xms
と-Xmx
を同じ値に設定できます。そうでない場合は、JVMが初期ヒープ・サイズを使用して開始され、ヒープ使用量とパフォーマンスのバランスが取れるまで、Javaヒープが増加します。
これらのデフォルト値は、他のパラメータおよびオプションの影響を受ける場合があります。デフォルト値を確認するには、-XX:+PrintFlagsFinal
オプションを使用し、出力から-XX:MaxHeapSize
を探します。たとえば、Linuxでは、次を実行できます。
java -XX:+PrintFlagsFinal <GC options> -version | grep MaxHeapSize
過剰なパラレル・コレクタ時間とOutOfMemoryError
ガベージ・コレクション(GC)で時間がかかりすぎると、パラレル・コレクタはOutOfMemoryError
をスローします。
ガベージ・コレクションに合計時間の98%より多く費やされ、ヒープのリカバリが2%未満である場合に、OutOfMemoryError
がスローされます。この機能は、ヒープが小さすぎるためにアプリケーションが長時間わたって処理が進まないまま実行中の状態に陥ることを回避する目的で設計されています。必要な場合は、コマンド行に-XX:-UseGCOverheadLimit
オプションを追加することで、この機能を無効にできます。