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

9 ガベージファースト・ガベージ・コレクタ

ガベージファースト(G1)ガベージ・コレクタはサーバー形式のガベージ・コレクタで、大容量のメモリーを搭載するマルチプロセッサ・マシンを対象としています。ガベージ・コレクション(GC)一時停止時間目標を高い確率で満たそうとしながら、高いスループットを実現します。グローバル・マーキングなどのヒープ全体オペレーションは、アプリケーション・スレッドと同時に実行されます。これによって、割込みがヒープまたはライブデータ・サイズに比例するのを防ぎます。

G1コレクタは、いくつかの技術によって高いパフォーマンスおよび一時停止時間目標を実現します。

ヒープは、均等サイズのヒープ・リージョン・セットに分割され、それぞれは連続する一連の仮想メモリーです。G1は、ヒープ全体のオブジェクトがライブかどうかを判断する、同時グローバル・マーキング・フェーズを実行します。マーキング・フェーズの完了後、G1はどのリージョンがほぼ空であるかを認識します。それらのリージョンを最初に収集し、通常は多くのスペースを解放します。このため、この方式のガベージ・コレクションがガベージファーストと呼ばれます。G1はその名が示すとおり、再生可能なオブジェクト(ガベージ)でいっぱいとなっている可能性の高いヒープ領域に対して、収集および圧縮活動を集中します。G1は、ユーザー定義の一時停止時間目標を満たすために一時停止予測モデルを使用し、指定された一時停止時間目標に基づいて収集するリージョン数を選択します。

G1は、ヒープの1つ以上のリージョンからヒープ上の単一リージョンにオブジェクトをコピーし、その処理内でメモリーを圧縮して解放します。この退避は、一時停止時間を減らし、スループットを向上させるために、マルチプロセッサ上で並列実行されます。このように、各ガベージ・コレクションで、G1は継続的に断片化を減らすために動作します。これは前の2つの方式の能力を上回っています。CMS (コンカレント・マーク・スイープ)ガベージ・コレクションは圧縮を行いません。パラレル圧縮はヒープ全体圧縮のみを実行するため、一時停止時間が長くなります。

G1はリアルタイム・コレクタではなことに注目することが重要です。設定された一時停止時間目標を高い確率で満たしますが、絶対確実ではありません。G1は、以前の収集からのデータに基づき、目標時間内に収集できるリージョン数を見積もります。このため、コレクタはリージョンを収集するコストの妥当に正確なモデルを持っており、これを使用して一時停止時間目標内でどのリージョンをどのくらい収集するかを判断します。

G1が最初の重点は、制限されたGCレイテンシで大きなヒープを必要とするアプリケーションを実行するユーザーに対して、ソリューションを提供することです。これは、およそ6GB以上のヒープ・サイズと、0.5秒未満の安定した予測可能な一時停止時間を意味します。

現在CMSまたはパラレル圧縮で実行しているアプリケーションが、次の特徴の1つ以上を備えている場合は、G1に切り替えることで利点が得られます。

  • Javaヒープの50%超がライブ・データで占められている。

  • オブジェクトの割当て率または昇格率が大きく変化する。

  • ガベージ・コレクションまたは圧縮によるアプリケーションの一時停止の長さが望ましくない(0.5から1秒を超える)。

G1は、コンカレント・マーク・スイープ・コレクタ(CMS)を長期的に置き換えるものとして計画されています。G1をCMSと比較すると、G1をより優れたソリューションたらしめる違いが見えてきます。違いの1つは、G1が圧縮するコレクタであることです。また、G1は、CMSコレクタより予測可能なガベージ・コレクション一時停止を提供し、ユーザーは望ましい一時停止目標を指定できます。

CMSと同様に、G1はGCによる一時停止の短縮が求められるアプリケーション向けに設計されています。

G1ではヒープを固定サイズのリージョン(図9-1「G1によるヒープの分割」ではグレーのボックスで表示)に分割します。

図9-1 G1によるヒープの分割

図9-1の説明が続きます
「図9-1 G1によるヒープの分割」の説明

G1は論理的には世代別です。空のリージョン・セットが論理的な若い世代として指定されます。この図では、若い世代を水色で表しています。その論理的な若い世代から割当てが行われ、若い世代がいっぱいになると、そのリージョン・セットはガベージ・コレクトされます(若いコレクション)。場合によって、若いリージョン・セット以外のリージョン(濃い青色の古い世代)が同時にガベージ・コレクトされることがあります。これは混合コレクションと呼ばれます。この図では、収集対象のリージョンが赤いボックスでマークされています。この図は、若いリージョンと古いリージョンの両方が収集されるので、混合コレクションを示したものです。このガベージ・コレクションは圧縮方式のコレクションで、初期状態が空の選択済リージョンにライブ・オブジェクトをコピーします。オブジェクトの年齢に基づいて、Survivorリージョン(「S」でマーク)または古いリージョン(特別な表示なし)にオブジェクトをコピーできます。「H」とマークされたリージョンには、リージョンの半分を超えるような大型(Humongous)オブジェクトが格納され、特殊な扱われ方をします(「ガベージファースト・ガベージ・コレクタ」「大型オブジェクトとHumongousの割当て」を参照)。

割当て(退避)の失敗

CMSと同様に、G1コレクタではアプリケーションの実行が継続中にコレクションの一部を実行するので、ガベージ・コレクタが空き領域をリカバリするよりも速く、アプリケーションがオブジェクトを割り当てるおそれがあります。CMSの類似する動作については、「コンカレント・マーク・スイープ(CMS)コレクタ」「並行モードの失敗」を参照してください。G1では、1つのリージョンから別のリージョンにライブ・データをコピー(退避)している最中に、この失敗(Javaヒープの枯渇)が発生します。コピーはライブ・データを圧縮するために行われます。ガベージ・コレクトされるリージョンの退避中に、空き(empty)リージョンが見つからないと、割当ての失敗が発生し(退避中のリージョンのライブ・データを割り当てる領域がないため)、stop-the-world (STW)フル・コレクションが実行されます。

フローティング・ガベージ

オブジェクトはG1コレクション中に寿命を終え、収集されない可能性があります。G1はsnapshot-at-the-beginning (SATB)と呼ばれる方式を使用して、すべてのライブ・オブジェクトがガベージ・コレクタによって検出されることを保証します。SATBでは、コンカレント・マーキング(ヒープ全体のマーキング)の開始時にライブであったすべてのオブジェクトをコレクションの目的においてはライブとみなす、と定められています。SATBでは、CMSのインクリメンタル更新と類似する方法でフローティング・ガベージを許可します。

一時停止

G1はライブ・オブジェクトを新しいリージョンにコピーするため、アプリケーションを一時停止します。このような一時停止は、若いリージョンのみが収集される若いコレクションの一時停止の場合もあれば、若いリージョンと古いリージョンを退避させる混合コレクションの一時停止の場合もあります。CMSと同様に、アプリケーションの停止中に、マーキングを完了するための最終マーキングまたは再マークの一時停止が行われます。CMSには初期マーキングの一時停止もありますが、G1では退避の一時停止内で初期マーキングが行われます。G1にはコレクションの最後に、部分的にSTW、また部分的にコンカレントなクリーンアップ・フェーズがあります。クリーンアップ・フェーズのSTW部分では空のリージョンを識別し、次のコレクションの候補となる古いリージョンを特定します。

カード・テーブルとコンカレント・フェーズ

ガベージ・コレクタがヒープ全体を収集しない場合(インクリメンタル・コレクション)、そのガベージ・コレクタは、収集されないヒープ部分から収集されるヒープ部分へのポインタがどこにあるかを把握している必要があります。これは一般的には世代別ガベージ・コレクタを対象としたもので、通常は収集されないヒープ部分は古い世代、収集されるヒープ部分は若い世代です。この情報を維持するためのデータ構造(古い世代から若い世代のオブジェクトへのポインタ)は記憶集合(Remembered Set)です。カード・テーブルは特定タイプの記憶集合です。Java HotSpot VMではバイト配列をカード・テーブルとして使用します。各バイトはカードと呼ばれます。カードはヒープ内のアドレス範囲に相当します。カードのDirty化とは、バイトの値をdirty値に変更することを意味します。dirty値には、カードが対象とするアドレス範囲内の古い世代から若い世代への新しいポインタが含まれている場合があります。

カードの処理とは、古い世代から若い世代へのポインタがあるかどうかカードを確認して、その情報を別のデータ構造へ転送するなど、場合によってなんらかの処理を行うことを意味します。

G1には、コンカレント・マーキング・フェーズがあり、そこではアプリケーションからの検出されたライブ・オブジェクトをマークします。コンカレント・マーキングは、(初期マーキング作業が行われる)退避の一時停止の終わりから再マークまでの期間です。コンカレント・クリーンアップ・フェーズでは、コレクションによって空状態になったリージョンを空きリージョン・リストに追加して、これらのリージョンの記憶集合をクリアします。また、同時絞込みスレッドを必要に応じて実行し、アプリケーション書込みによってdirty化され、リージョン間の参照が記録されている可能性のあるカード・テーブルのエントリを処理します。

コンカレント・コレクション・サイクルの開始

前に説明したように、混合コレクションでは若いリージョンと古いリージョンの両方がガベージ・コレクトされます。古いリージョンを収集する場合、G1はヒープ内のライブ・オブジェクトの完全なマーキングを行います。このようなマーキングはコンカレント・マーキング・フェーズで実行されます。コンカレント・マーキング・フェーズは、Javaヒープ全体の占有率がパラメータInitiatingHeapOccupancyPercentの値に到達すると開始されます。このパラメータの値は、コマンド行オプション-XX:InitiatingHeapOccupancyPercent=<NN>で設定します。InitiatingHeapOccupancyPercentのデフォルト値は45です。

一時停止時間目標

G1の一時停止時間目標は、フラグMaxGCPauseMillisで設定します。G1は予測モデルを使用して、指定された目標一時停止時間内に実行可能なガベージ・コレクションの作業量を判断します。G1では、コレクションの最後に、次回のコレクションで収集するリージョン(コレクション・セット)を選択します。そのコレクション・セットには若いリージョンが含まれ、その合計サイズによって、論理的な若い世代のサイズが決まります。これは、G1がGC一時停止の長さを制御しているコレクションの、若いリージョンの設定数によって、ある程度決まっています。他のガベージ・コレクタと同様に、若い世代のサイズはコマンド行で指定できますが、そうすることによってG1が目標一時停止時間を達成できなくなる可能性があります。一時停止時間目標の他に、一時停止の実行間隔を指定することも可能です。一時停止時間目標とともに、この時間範囲(GCPauseIntervalMillis)での最小ミューテータ使用率も指定できます。MaxGCPauseMillisのデフォルト値は200ミリ秒です。GCPauseIntervalMillisのデフォルト値(0)は、時間範囲に要件がない場合と同等です。

目次      

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