kagamihogeの日記

kagamihogeの日記です。

JEP 351: ZGC: Uncommit Unused Memoryをテキトーに訳した

http://openjdk.java.net/jeps/351

JEP 351: ZGC: Uncommit Unused Memory

Owner    Per Liden
Type    Feature
Scope   Implementation
Status  Candidate
Component   hotspot / gc
Discussion  hotspot dash gc dash dev at openjdk dot java dot net
Effort  S
Duration    S
Reviewed by Mikael Vidstedt, Stefan Karlsson
Created 2019/03/08 10:35
Updated 2019/03/14 21:48
Issue   8220347

Summary

未使用ヒープメモリをOSに返却するようZGCを改良します。

Motivation

現行のZGCは、あるメモリが長時間未使用だとしても、uncommitおよびそのメモリのOS返却を行いません。この振る舞いはあらゆる種類のアプリケーションと環境に最適では無く、特にメモリフットプリントが関心事である場合に顕著です。たとえば、

  • リソース使用分で請求されるコンテナ環境。
  • アプリケーションが長期間アイドルしたり、多数のアプリケーションでリソース共有や競合が発生する環境。
  • アプリケーション実行中にヒープ空間に対する要求が極めて変化する場合。たとえば、スタートアップ中に必要なヒープが通常状態よりも大量に必要となるケース。

HotSpot, G1とShenandoahのその他のGCは、今日ではこれら機能を有しており、上記カテゴリのユーザに受け入れられています。ZGCにこれら機能を追加し、同カテゴリのユーザにZGCを受け入れやすくします。

Description

ZGCヒープはZPagesというヒープ領域セットで構成しています。ZPageはそれぞれ可変量のコミット済ヒープメモリと関連付けられています。ZGCがヒープをコンパクト化すると、ZPageは解放されてZPageCacheというページキャッシュに挿入されます。ページキャッシュのZPagesは新規ヒープアロケーションに対して再使用可能状態にあり、アロケーション後はキャッシュから削除されます。ページキャッシュはパフォーマンスにとって極めて重要で、これはメモリのコミットとuncommitが高価なオペレーションなためです。

ページキャッシュのZPagesはヒープの未使用部分を表現し、これはuncommitとOS返却が"可能(could)"です。このためメモリuncommitはページキャッシュの適当に選択したZPagesを単に切り離せば良く、それからページに関連付けられたメモリをuncommitします。ページキャッシュはLRUと分離サイズ(small, medium, large)でZPagesを維持する仕組みがあるため、ZPages切り離しのメカニズムとメモリuncommitは比較的単純です。チャレンジングなのは、キャッシュからZPageを切り離すタイミングの決定ポリシーです。

シンプルなポリシーとしてはタイムアウトや、ページキャッシュを切り離すZPage生存時間を指定するディレイ値があります。タイムアウトは妥当なデフォルト値で、これはコマンドラインオプションでオーバーライドします。Shenandoah GCはこれと似たポリシーを持ち、デフォルト値5分でコマンドラインオプション-XX:ShenandoahUncommitDelay=<milliseconds>でオーバーライドします。

上記のようなポリシーは妥当な動作をします。しかし、もっと賢い切り離しポリシー設定が可能で、これは別途コマンドラインオプションを必要としません。たとえば、GC頻度や何らかのデータに基づいて最適なタイムアウトを得るヒューリスティックがあります。現時点では採用ポリシーは決定していません。各種ポリシーを評価予定です。まず最初は、シンプルなタイムアウトポリシーと-XX:ZUncommitDelay=<seconds>を提供し、それから、より賢いポリシー(もし見つかれば)を導入します。

ポリシーが決定したとしても、ヒープが最小サイズ(-Xms)以下になるようなZGCのメモリuncommitを絶対にしません。つまり、最小ヒープサイズ(-Xms)が最大ヒープサイズ(-Xmx)と等しい状態でJVMを開始する場合、uncommit機能は無効化します。

最後に、Linux/x64のZGCはヒープ返却にtmpfsやhugetlbfsファイルを使います。これらファイルのメモリuncommitはFALLOC_FL_PUNCH_HOLEサポートのあるfallocate(2)が必要で、これが最初に導入されたのはinux 3.5 (tmpfs)と4.3 (hugetlbfs)です。ZGCはこれより古いLinuxでも以前同様に動作する必要があります。ただし、uncommit機能が無効化される点は除きます。

Testing

  • 開発するuncommit機能の検証に一つ以上のjtregテストを使用する。
  • 既存のベンチマーク、SPECjbbとSPECjvmなど、でデフォルトポリシー使用時にレイテンシやスループット劣化が見られないことを検証する。

Risks and Assumptions

現行プランではuncommit機能は常にONで、明示的な無効化オプションはありません。ただし、-Xms-Xmxを同一値にすることで間接的には可能です。これは余計なオプション追加をしないというZGCの意志の現れです。明示オプション(-XX:-ZUncommit)が必要かどうかは時が決めるでしょう。現状、必要でないと判断しています。