ZGC | Using -XX:SoftMaxHeapSize

原文はこちら。
The original article was written by Per Lidén (software engineer, Oracle).
https://malloc.se/blog/zgc-softmaxheapsize

JDK 13で新しいGCオプションである -XX:SoftMaxHeapSize=<size> が導入されました。現在のところ、このオプションをサポートする唯一のGCはZGCのみですが、現在G1でもサポートするように作業中です。このオプションが比較的新しいものでまだ広く知られていないと思われるため、いつ、どのように使うべきかをしたためておきます。

JDK 13
https://openjdk.java.net/projects/jdk/13/
Main – ZGC – OpenJDK Wiki
https://wiki.openjdk.java.net/display/zgc/Main
[JDK-8236073] G1: Use SoftMaxHeapSize to guide GC heuristics
https://bugs.openjdk.java.net/browse/JDK-8236073

When is -XX:SoftMaxHeapSize useful?

名前が示すように、この新しいオプションは、Javaヒープが大きくなるサイズにソフトリミットを設定します。これを設定すると、GCはこのソフト最大ヒープサイズを超えてヒープサイズが大きくならないように努力します。しかし、メモリ割り当てに失敗するか、またはOutOfMemoryErrorをスローする可能性があるために残された選択肢が一つしかない場合など、本当に必要な場合には、 GCは指定サイズを超えてもヒープが大きくなることを許可します。

ソフト最大ヒープサイズを設定することが有用な様々なユースケースがあります。例えば以下のようなユースケースが上げられます。

  • ヒープスペースの一時的な増加に対応する能力を維持しつつ、ヒープのフットプリントを抑えたい場合
  • または、アロケーション・レートやライブ・セット・サイズの予期せぬ増加により、アロケーション・ストールに遭遇したり、OutOfMemoryErrorが発生したりすることがないように、信頼性を高めたい、つまり安全第一でいきたい場合

上記の最初のユースケースを説明するために、例を作ってみましょう。通常の状態でのワークロードは2Gのヒープを必要としているとします。しかし、時折、ワークロードが急増することがあります(ある週/月の特定の日に多くのユーザーを引き付けるサービスやそれに類したものを提供しているのかもしれません)。このようなワークロードの増加に伴い、アプリケーションが正常に動作するためには、例えば5Gが必要になってきます。この状況に対処するために、通常は最大ヒープサイズ(-Xmx)を5Gに設定して、時折発生するワークロードのスパイクをカバーすることになります。しかし、それはまた、必要のないときには98%(というか何か)の3Gのメモリを無駄にしてしまうことを意味します。なぜなら、未使用の 3G はまだ Java ヒープに縛られているからです。

ここでソフト最大ヒープサイズが役立ちます。ZGC の未使用メモリのアンコミット(Uncommit Unused Memory)機能と組み合わさり、ケーキを食べてもいいようにしてくれます。最大ヒープサイズをアプリケーションが必要とする最大ヒープ量に設定し(この場合は -Xmx5G)、ソフト最大ヒープサイズをアプリケーションが通常の状態で必要とする量に設定します(この場合は -XX:SoftMaxHeapSize=2G)。これで、常に 3G を無駄にすることなく、ワークロードのスパイクをうまく処理できるようになりました。ワークロードの急増が終わり、メモリの需要が通常の状態に戻ると、ZGC はヒープを縮小し、-XX:SoftMaxHeapSize の設定を尊重して最善を尽くします。余分な 3G のヒープがしばらく使用されずに放置されていた場合、ZGC はそのメモリのコミットを解除し、他のプロセス(または OS のページキャッシュなど)が使用できるようにOSに戻します。

JEP 351: ZGC: Uncommit Unused Memory (Experimental)
https://openjdk.java.net/jeps/351

Change -XX:SoftMaxHeapSize at runtime

SoftMaxHeapSizeオプションも管理可能で、JVMを再起動しなくても実行時に変更できます。管理可能なJVMオプションは、以下のようにHotSpotDiagnosticMXBeanまたはjcmdを使用して、実行時に変更することができます。

jcmd <pid> VM.set_flag SoftMaxHeapSize <size>

ソフト最大ヒープサイズは、最大ヒープサイズよりも大きな値を設定することはできません。コマンドラインで設定されていない場合、ソフト最大ヒープサイズはデフォルトで最大ヒープサイズと同じ値になります。

Uncommit aggressiveness

ZGC が未使用のメモリをどれだけ積極的にアンコミットするかは -XX:ZUncommitDelay=<seconds> で制御できます(デフォルトは300秒、つまり5分)。言い換えれば、デフォルトでは、メモリはアンコミットの対象となる前に5分間未使用である必要があります。メモリのコミットとアンコミットは比較的高価な操作であることに注意が必要です。あまりにも積極的な(短時間での)アンコミットは、アンコミットされたメモリがすぐに再びコミットされる原因となり、CPU サイクルの浪費となり、最終的にはアプリケーションの全体的なパフォーマンスにも影響を与える可能性があります。

TL;DR

-XX:SoftMaxHeapSize=2G -Xmx5Gを使うと、最大ヒープ利用量を2Gに保ちつつ、メモリアロケーションの失敗やOutOfMemoryErrorが発生してしまうような状態であれば、ヒープを最大5Gまで大きくすることを許可するようにZGCに対し指示します。これはメモリフットプリントを小さく保ちながらも、ヒープスペースの一時的な増加を処理する能力を維持したい場合に便利です。

ZGCの詳細情報は、OpenJDK Wiki、Inside JavaのGCの章、もしくはこのブログをご覧ください。

Main – ZGC – OpenJDK Wiki
https://wiki.openjdk.java.net/display/zgc/Main
Gc – Inside Java
https://inside.java/tag/gc
perliden(原文著者のブログ)
https://malloc.se/

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中