開発者ドキュメント

jvm-zgc-garbage-collector

ZGCの紹介:スケーラブルで実験的な低遅延JVMガベージコレクター

1. 前書き

今日、アプリケーションが数千または数百万ものユーザーに同時にサービスを提供することは珍しくありません。 このようなアプリケーションには膨大な量のメモリが必要です。 ただし、そのすべてのメモリを管理すると、アプリケーションのパフォーマンスに簡単に影響する場合があります。
この問題に対処するために、Java 11ではhttps://docs.oracle.com/en/java/javase/11/gctuning/z-garbage-collector1.html[Z Garbage Collector](ZGC)を実験的なガベージコレクター( GC)実装。
このチュートリアルでは、* ZGCがマルチテラバイトヒープでも短い休止時間を維持する方法を説明します*。

2. 主なコンセプト

ZGCを理解するには、https://www.baeldung.com/java-memory-management-interview-questions [メモリ管理]およびlink:/の背後にある基本的な概念と用語を理解する必要があります。 jvm-garbage-collectors [ガベージコレクタ]。

2.1. メモリ管理

*物理メモリ*は、ハードウェアが提供するRAMです。
オペレーティングシステム(OS)は、各アプリケーションに*仮想メモリ*スペースを割り当てます。
もちろん、仮想メモリは物理メモリに保存され、OSは2つの間のマッピングを維持する責任があります。 このマッピングには通常、ハードウェアアクセラレーションが含まれます。

2.2. ガベージコレクション

Javaアプリケーションを作成するときに、割り当てたメモリを解放する必要はありません。ガベージコレクターがそれを行うためです。 要約すると、* GCは、参照のチェーンを通じてアプリケーションから到達できるオブジェクトを監視し、到達できないオブジェクトを解放します*。
それを実現するために、ガベージコレクターには複数のフェーズがあります。

2.3. GCフェーズのプロパティ

GCフェーズにはさまざまなプロパティがあります。
  • * parallel *フェーズは複数のGCスレッドで実行できます

  • * serial *フェーズは単一のスレッドで実行されます

  • * stop the world *フェーズはアプリケーションコードと同時に実行できません

  • * concurrent *フェーズはバックグラウンドで実行できますが、アプリケーションは
    その仕事をする

  • * incremental *フェーズは、すべての作業を完了する前に終了できます
    後で続けます

    上記の手法にはすべて長所と短所があることに注意してください。 たとえば、アプリケーションと同時に実行できるフェーズがあるとしましょう。 このフェーズのシリアル実装には、全体的なCPUパフォーマンスの1%が必要で、1000ミリ秒実行されます。 対照的に、並列実装はCPUの30%を利用し、50ミリ秒で作業を完了します。
    この例では、*パラレルソリューションはより複雑で、スレッドを同期する必要があるため、全体でより多くのCPUを使用します*。 CPUヒーブアプリケーション(バッチジョブなど)の場合、効率的な作業を行うための計算能力が低いため、これは問題です。
    もちろん、この例には数字が含まれています。 ただし、すべてのアプリケーションに独自の特性があるため、GC要件が異なることは明らかです。
    詳細については、https://www.baeldung.com/java-memory-management-interview-questions [Javaメモリ管理に関する記事]をご覧ください。

3. ZGCの概念

実証済みのGCテクニックに加えて、ZGCは2つの新しい概念を導入します。それは、ポインターの色付けとロードバリアです。

3.1. ポインターの色付け

ポインターは、仮想メモリ内のバイトの位置を表します。 ただし、そのために必ずしもポインターのすべてのビットを使用する必要はありません。一部のビットはポインターのプロパティを表すことができます*。 これが、ポインターの色付けと呼ばれるものです。
32ビットでは、4ギガバイトに対応できます。 最近では、これよりも多くのメモリを持つ構成が非常に一般的であるため、これらの32ビットをカラーリングに使用できないことは明らかです。 したがって、ZGCは64ビットポインターを使用します。 つまり、* ZGCは64ビットプラットフォームでのみ使用可能です*。
link:/uploads/zgc-pointer-100x14.png%20100w []
ZGCポインターは、アドレス自体を表すために42ビットを使用します。 その結果、ZGCポインターは4テラバイトのメモリ空間をアドレス指定できます。
さらに、ポインターの状態を保存する4ビットがあります。
  • * finalizable *ビット-オブジェクトはファイナライザーを介してのみ到達可能です

  • * remap *ビット–参照は、現在のアドレスを指します
    オブジェクト(再配置を参照)

  • * marked0 および marked1 *ビット–これらは到達可能フラグに使用されます
    オブジェクト

    これらのビットをメタデータビットとも呼びました。 ZGCでは、これらのメタデータビットの1つだけが1です。

3.2. マルチマッピング

マルチマッピングとは、*仮想メモリの複数の範囲を物理メモリにマップする*ことを意味します。 ZGCでは、これらの範囲は前述のメタデータビットのみが異なります。
ポインターの色付けは、アドレス自体にアクセスするために有用なビットをマスクする必要があるため、参照のコストが高くなることに注意してください。 ただし、* ZGCは、4つのメタデータビットのうち1つが1 *になるという事実により、このコストをバイパスします。 この方法では、マッピングする範囲は4つしかなく、マッピングはオペレーティングシステムによって処理されます。 さらに、ファイナライズ可能なポインターを逆参照したくないため、これらの範囲のうち3つのみを使用します。
link:/uploads/zgc-multimapping-100x47.png%20100w []

3.3. ロードバリア

ロードバリアは、スレッドがヒープから参照をロードするときに実行されるコードの一部です。たとえば、オブジェクトの非プリミティブフィールドにアクセスする場合などです。
ZGCでは、ロードバリアは参照のメタデータビットをチェックします。 これらのビットに応じて、ZGCは参照を取得する前に参照に対して何らかの処理を実行する場合があります。 したがって、まったく異なる参照が生成される場合があります。

3.4. マーキング

マーキングは、ガベージコレクターが*到達できるオブジェクトを決定する*プロセスです。 到達できないものはゴミと見なされます。 ZGCは、マーキングを3つのフェーズに分割します。
link:/uploads/zgc-marking-100x56.png%20100w []
最初のフェーズは、世界停止フェーズです。 このフェーズでは、ルート参照を探してマークします。 *ルート参照は、ローカル変数や静的フィールドなど、ヒープ内のオブジェクトに到達するための開始点です。 通常、ルート参照の数は少ないため、このフェーズは短くなります。
次のフェーズは並行フェーズです。 このフェーズでは、ルート参照から開始して、オブジェクトグラフを走査します。 到達したすべてのオブジェクトにマークを付けます。*また、ロードバリアがマークされていない参照を検出すると、それもマークします。
最後の段階は、弱参照のようないくつかのエッジケースを処理するための世界停止段階でもあります。
この時点で、どのオブジェクトに到達できるかがわかります。
ZGCは、マーキングに_marked0_および_marked1_メタデータビットを使用します。

3.5. 移転

新しいオブジェクトにメモリを割り当てる必要がある場合、2つの戦略に従うことができます。
最初に、オブジェクトを保持するのに十分な空き領域がないかメモリをスキャンします。 メモリのスキャンは高価な操作です。 さらに、オブジェクト間にギャップがあるため、メモリが断片化されます。 これらのギャップを最小限に抑えるには、さらに多くの処理能力を使用します。
もう1つの戦略は、頻繁に*断片化されたメモリ領域からオブジェクトをよりコンパクトな形式の空き領域に再配置することです*。 より効果的にするために、メモリ空間をブロックに分割します。 ブロック内のすべてのオブジェクトを再配置するか、どれも再配置しません。 この方法では、メモリ内に空のブロック全体が存在することがわかっているため、メモリの割り当てが高速になります。
ZGCでは、再配置も3つのフェーズで構成されます。
  1. 並行フェーズでは、再配置するブロックを探して配置します
    再配置セット内。

  2. Stop the Worldフェーズは、再配置内のすべてのルート参照を再配置します
    参照を設定および更新します。

  3. 並行フェーズは、再配置に残っているすべてのオブジェクトを再配置します
    フォワードテーブルの古いアドレスと新しいアドレスの間のマッピングを設定して保存します。

3.6. 再マッピング

再配置フェーズでは、再配置されたオブジェクトへのすべての参照を書き換えていないことに注意してください。 したがって、これらの参照を使用すると、目的のオブジェクトにアクセスできません。 さらに悪いことに、ごみにアクセスできました。
ZGCは、ロードバリアを使用してこの問題を解決します。 *ロードバリアは、再マッピングと呼ばれる手法で、再配置されたオブジェクトを指す参照を修正します。*
次の図は、再マッピングの仕組みを示しています。
link:/uploads/zgc-remap-flow-100x60.png%20100w []

4. ZGCを有効にする方法

アプリケーションを実行するときに、次のコマンドラインオプションでZGCを有効にできます。
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
ZGCは実験的なGCであるため、正式にサポートされるまでには時間がかかることに注意してください。

5. 結論

この記事では、ZGCがアプリケーションの一時停止時間を短くして大きなヒープサイズをサポートすることを意図していることを確認しました。
この目標を達成するために、色付きの64ビットポインター、ロードバリア、再配置、再マッピングなどの手法を使用します。
モバイルバージョンを終了