はじめに
G1GC は、full GC か concurrent cycle で Java Heep を解放しますが、G1GC は full GC を回避するように試み、concurrent cycle も ヒープ占有率とアロケーションアクティビティを基にトリガされるため、多くのケースで Java Heep は解放されません。
メモリリソースの一部しか利用していない状況でも、G1 は Heep を保持し続けるため、リソース使用分に応じて課金されるコンテナ環境などでは、この挙動はデメリットになります。 これが改善できれば、Tomcat サーバの実際の使用を基にしたプロトタイプテストにおいて、夜間のアイドル時間帯で、コミット済みメモリの 85% を減少可能としています。
JDK 12 では、上記改善のため以下の3つのJVMオプションが追加され、G1 GC からのメモリ返却が制御可能になりました。
- G1PeriodicGCInterval
- G1PeriodicGCSystemLoadThreshold
- G1PeriodicGCInvokesConcurrent
G1PeriodicGCInterval
G1 が定期的なガベージ・コレクションをトリガーする必要があるかどうかを確認する間隔(ミリ秒)を指定します。 デフォルトではゼロに設定されており、これは無効を意味します。
-XX:G1PeriodicGCInterval=60000 // 60秒間隔
G1PeriodicGCIntervalミリ秒以上が、以前のガベージコレクション休止から経過しており、この時点で進行中の同時サイクルがない場合、アプリケーションは非アクティブとみなされ、G1 は定期的なガベージ・コレクションをトリガーします。
G1PeriodicGCSystemLoadThreshold
G1PeriodicGCInterval によるガベージ・コレクションを、システム負荷が高い場合に実行させないようにします。
現在のシステム負荷(ホストの getloadavg()
コールで返される1分間の平均システム負荷値)がこの値よりも高いと、定期的なガベージ・コレクションはキャンセルされます。
デフォルトはゼロで、この条件は無視されます。
-XX:G1PeriodicGCSystemLoadThreshold=0.0
G1PeriodicGCInvokesConcurrent
定期的なガベージ・コレクションのタイプ(コンカレントかそうではないか)を設定します。
設定されている場合は、定期的なガベージ・コレクションでコンカレント・マーキングがトリガーされるか、既存のコレクション・サイクルが継続されます。
設定されていない場合はフルGCがトリガーされます。
-XX:+G1PeriodicGCInvokesConcurrent
まとめ
JDK 12 から、G1 GC でヒープを OS に返却するオプションが追加されました。
デフォルトはOFFになっているため、G1PeriodicGCInterval
を設定すればヒープが定期的に開放されるようになります。挙動を細かく制御したい場合は、G1PeriodicGCSystemLoadThreshold
と G1PeriodicGCInvokesConcurrent
が用意されています。
アクティブな時間帯とアイドルな時間帯が分かれるサーバアプリケーションやクライアントアプリケーションなどにおいては、G1PeriodicGCInterval
を設定しておくのが良いでしょう。