Java Platform, Standard Edition HotSpot Virtual Machineガベージ・コレクション・チューニング・ガイド
目次      

6 パラレル・コレクタ

パラレル・コレクタ(ここではスループット・コレクタとも呼ばれる)はシリアル・コレクタに似た世代別コレクタで、主な違いは複数のスレッドを使用してガベージ・コレクションを高速化することです。パラレル・コレクタを有効にするには、コマンド行オプション-XX:+UseParallelGCを使用します。デフォルトで、このオプションを使用すると、ガベージ・コレクションのオーバーヘッドをさらに減らすため、マイナー・コレクションもメジャー・コレクションも並列実行されます。

パラレル・コレクタでは、N個(Nは9以上)のハードウェア・スレッドを使用するマシン上で、Nの固定比率をガベージ・コレクタのスレッド数として使用します。Nの値が大きい場合、この比率は約5/8です。Nの値が8未満の場合、使用される数値はNです。特定のプラットフォームでは、比率は5/16に低下します。指定のガベージ・コレクタ・スレッド数はコマンド行オプション(後述)を使用して調整できます。プロセッサが1個のホストでは、並列実行にオーバーヘッド(同期化など)が必要になるため、パラレル・コレクタはシリアル・コレクタよりもパフォーマンスが低くなる可能性があります。ただし、中規模から大規模なヒープを使用してアプリケーションを実行する場合は、2個のプロセッサを搭載したマシンではシリアル・コレクタよりもパフォーマンスが若干向上し、プロセッサが3個以上利用可能場合はシリアル・コレクタよりも大幅にパフォーマンスが向上するのが一般的です。

ガベージ・コレクタのスレッド数は、コマンド行オプション-XX:ParallelGCThreads=<N>で制御できます。コマンド行オプションを使用してヒープの調整を明示的に行う場合、パラレル・コレクタで高いパフォーマンスを実現するために必要なヒープ・サイズは、シリアル・コレクタで必要なヒープ・サイズと同じです。ただし、パラレル・コレクタは、コレクションによる一時停止を短縮する目的でのみ有効にしてください。マイナー・コレクションでは複数のガベージ・コレクタ・スレッドが使用されているため、コレクション時の若い世代からTenured世代への昇格に伴い断片化が発生する可能性があるからです。マイナー・コレクションで使用されている各ガベージ・コレクション・スレッドは昇格のためにTenured世代の一部を確保し、その使用可能な領域が「昇格バッファ」に分割されるために、断片化の影響を受ける可能性があります。ガベージ・コレクタ・スレッドの数を減らし、Tenured世代のサイズを増やすことによって、この断片化の影響は低減します。

世代

前に説明したように、パラレル・コレクタでは世代の配置が異なります。その配置を、図6-1「パラレル・コレクタでの世代の配置」に示しています。

図6-1 パラレル・コレクタでの世代の配置

図6-1の説明が続きます
「図6-1 パラレル・コレクタでの世代の配置」の説明

パラレル・コレクタ・エルゴノミクス

server-classマシンでは、パラレル・コレクタがデフォルトで選択されます。また、パラレル・コレクタでは自動調整の方法を使用しているので、ユーザーは世代サイズや他の低レベルのチューニング詳細ではなく、特定の動作を指定できます。ガベージ・コレクションの最大一時停止時間、スループットおよびフットプリント(ヒープ・サイズ)を指定できます。

  • ガベージ・コレクションの最大一時停止時間: 最大一時停止時間目標は、コマンド行オプション-XX:MaxGCPauseMillis=<N>で指定します。これは、<N>ミリ秒以下の一時停止時間が望ましいというヒントとして解釈されます。デフォルトでは、最大一時停止時間目標はありません。一時停止時間目標が指定されている場合、ガベージ・コレクションによる一時停止を指定された値以内に維持するよう、ヒープ・サイズとその他のガベージ・コレクション関連パラメータが調整されます。このような調整に伴い、ガベージ・コレクタによりアプリケーションの全体的なスループットが低下する場合があるので、望ましい一時停止時間目標を必ずしも満たせるとはかぎりません。

  • スループット: スループット目標は、ガベージ・コレクションの実行に消費された時間とガベージ・コレクション以外で消費された時間(アプリケーション時間と呼ばれる)の観点から測定されます。この目標はコマンド行オプション-XX:GCTimeRatio=<N>で指定され、ガベージ・コレクション時間のアプリケーション時間に対する比率を1 / (1 + <N>)に設定します。

    たとえば、-XX:GCTimeRatio=19は、ガベージ・コレクションに合計時間の20分の1 (5%)という目標を設定します。デフォルト値は99で、ガベージ・コレクションに1%という時間の目標を設定します。

  • フットプリント: ヒープの最大フットプリントはオプション-Xmx<N>を使用して指定します。また、コレクタには、他の目標が満たされている場合はヒープ・サイズを最小化するという暗黙の目標があります。

目標の優先度

各目標には次の順序で対処します。

  1. 最大一時停止時間目標

  2. スループット目標

  3. 最少フットプリント目標

最大一時停止時間目標を最初に満たします。これを満たした上で、スループット目標に対処します。同様に、先の2つの目標を満たした上で、フットプリント目標を検討します。

世代サイズの調整

コレクタが保持する平均一時停止時間などの統計は、各コレクションの終了時に更新されます。その後で、目標を満たしているか確認するためのテストと、必要に応じて世代サイズの調整が行われます。例外として、明示的なガベージ・コレクション(System.gc()の呼出し)は、世代サイズの統計保持や調整上、無視されます。

世代サイズの拡大と縮小は、適切なサイズになるまで段階的に増減されるように、世代サイズの一定割合を単位として徐々に調整されます。拡大と縮小はそれぞれ別の比率で行われます。デフォルトで、世代の拡大率は20%、縮小率は5%です。拡大率はコマンド行オプション-XX:YoungGenerationSizeIncrement=<Y> (若い世代の場合)および-XX:TenuredGenerationSizeIncrement=<T> (Tenured世代の場合)で制御します。世代の縮小率はコマンド行フラグ-XX:AdaptiveSizeDecrementScaleFactor=<D>で調整します。拡大率がXパーセントの場合、縮小率はX/Dパーセントになります。

コレクタの起動時に世代の拡大が決定されると、増加率が割り増しされます。この割増しはコレクションの回数に伴って減衰し、長期的な影響はありません。割増しの目的は、起動時のパフォーマンスを向上させることです。縮小率に割増しはありません。

最大一時停止時間目標が満たされていない場合、一度に縮小できるのは1つの世代のサイズのみです。2つの世代の一時停止時間が目標を超えている場合、一時停止時間が大きい方の世代のサイズが先に縮小されます。

スループット目標が満たされていない場合は、両方の世代サイズが増加されます。どちらも、ガベージ・コレクション合計時間に占めるそれぞれの割合に比例して増加されます。たとえば、若い世代のガベージ・コレクション時間が合計コレクション時間の25%であり、若い世代の完全な拡大率が20%単位である場合、若い世代は5%単位で増加することになります。

デフォルト・ヒープ・サイズ

コマンド行で初期ヒープ・サイズと最大ヒープ・サイズが指定されていない場合、これらのサイズはマシン上のメモリー容量に基づいて計算されます。

クライアントJVMのデフォルト・ヒープ・サイズの初期値と最大値

デフォルトの最大ヒープ・サイズは、物理メモリーの半分(最大で192MBの物理メモリー・サイズまで)、それ以外の場合、物理メモリー・サイズの1/4 (最大で1GBの物理メモリー・サイズまで)です。

たとえば、マシンの物理メモリーが128MBの場合の最大ヒープ・サイズは64MB、物理メモリーが1GB以上の場合の最大ヒープ・サイズは256MBになります。

最大ヒープ・サイズは、それを必要とするだけのオブジェクトが作成される場合を除き、実際にはJVMによって使用されません。初期ヒープ・サイズと呼ばれる、はるかに少ない量がJVMの初期化時に割り当てられます。この容量は少なくとも8MB、およびそれ以外の場合、物理メモリーの1/64 (最大で1GBの物理メモリー・サイズまで)です。

若い世代に割り当てられる最大領域サイズは、全ヒープ・サイズの1/3です。

サーバーJVMのデフォルト・ヒープ・サイズの初期値と最大値

サーバーJVM上のデフォルト・ヒープ・サイズの初期値と最大値は、より高いデフォルト値が可能であることを除き、クライアントJVMの場合と同様です。32ビットJVMのデフォルトの最大ヒープ・サイズは、4GB以上の物理メモリーがある場合、最大で1GBです。64ビットJVMのデフォルトの最大ヒープ・サイズは、128GB以上の物理メモリーがある場合、最大で32GBです。これらの値は、いつでも直接に指定して、より高い(または低い)初期および最大ヒープを設定できます。次の項を参照してください。

ヒープ・サイズの初期値と最大値の指定

フラグ-Xms (初期ヒープ・サイズ)および-Xmx (最大ヒープ・サイズ)を使用して、初期および最大のヒープ・サイズを指定できます。アプリケーションがうまく動作するために必要なヒープ領域がわかっている場合は、-Xms-Xmxを同じ値に設定できます。そうでない場合は、JVMが初期ヒープ・サイズを使用して開始され、ヒープ使用量とパフォーマンスのバランスが取れるまで、Javaヒープが増加します。

これらのデフォルト値は、他のパラメータおよびオプションの影響を受ける場合があります。デフォルト値を確認するには、-XX:+PrintFlagsFinalオプションを使用し、出力からMaxHeapSizeを探します。たとえば、LinuxまたはSolarisでは、次を実行できます。

java -XX:+PrintFlagsFinal <GC options> -version | grep MaxHeapSize

過剰なGC時間とOutOfMemoryError

ガベージ・コレクション(GC)に時間がかかりすぎると、パラレル・コレクタはOutOfMemoryErrorをスローします。具体的には、ガベージ・コレクションに合計時間の98%より多く費やされ、ヒープのリカバリが2%未満である場合に、OutOfMemoryErrorがスローされます。この機能は、ヒープが小さすぎるためにアプリケーションが長時間わたって処理が進まないまま実行中の状態に陥ることを回避する目的で設計されています。必要な場合は、コマンド行に-XX:-UseGCOverheadLimitオプションを追加することで、この機能を無効にできます。

測定

パラレル・コレクタからの冗長ガベージ・コレクタ出力は、シリアル・コレクタからのものと基本的には同じです。

目次      

Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.