Hazelcast Jet on Generational ZGC

原文はこちら。
The original article was written by
https://kstefanj.github.io/2023/11/07/hazelcast-on-generational-zgc.html

数年前、Hazelcast Jetの開発者たちは、当時利用可能だったさまざまなGCを試してみることにしました。その結果が2020年のこの一連のブログにあり、ZGCの結果は非常に有望に見えました。

Hazelcast Jet
https://jet-start.sh
Performance of Modern Java on Data-Heavy Workloads: Real-Time Streaming
https://jet-start.sh/blog/2020/06/09/jdk-gc-benchmarks-part1

あれから3年が経過し、ZGCにさらに多くの作業が費やされました。JDK15で本番運用に耐えるようになり、JDK16でConcurrent stack scanが追加され、そして今、JDK21で世代サポートが追加されたことで、低レイテンシーのワークロードにさらに適したGCになりました。

JEP 377: ZGC: A Scalable Low-Latency Garbage Collector (Production)
https://openjdk.java.net/jeps/377
JEP 376: ZGC: Concurrent Thread-Stack Processing
https://openjdk.org/jeps/376
JEP 439: Generational ZGC
https://openjdk.org/jeps/439

このエントリでは、あるHazelcast Jetの実験から、Generational ZGCがどのように動作するかを見てみます。

Generational ZGC

JDK21がリリースされたばかりですが、その中の大きな機能の1つがGenerational ZGC(世代別ZGC)です。

The Arrival of Java 21!
https://inside.java/2023/09/19/the-arrival-of-java-21/
https://logico-jp.io/2023/09/20/the-arrival-of-java-21/

世代サポートにより、ZGCはヒープを2世代に分けることができます(他のほとんどのOpenJDKガベージコレクタと同様です)。

  • 新しく割り当てられたオブジェクトのためのyoung generation
  • 数多くのGCサイクルを生き延びたオブジェクトが行き着くold generation

これには、young generationをより頻繁にGCできるという利点があり、ほとんどのオブジェクトがガベージとみなされることを期待している(the weak generational hypothesisを参照)。

Garbage Collector Implementation
https://docs.oracle.com/en/java/javase/21/gctuning/garbage-collector-implementation.html#GUID-71D796B3-CBAB-4D80-B5C3-2620E45F6E5D

ほとんどのオブジェクトがガベージであれば、収集のコストは下がります。つまり、Generational ZGCはレガシーZGC(世代別でないバージョン)と比べて、より頻繁にGCを行い、より少ないリソースでより多くのメモリを回収できます。

ZGCへの世代追加は、3年以上にわたって開発されてきた非常に大きな機能であり、それについてより詳細な情報を知りたい場合は、JEPを読んだり、JVMLSの動画(Generational ZGC and Beyond)を見たりすることをお勧めします。

JEP 439: Generational ZGC
https://openjdk.org/jeps/439

Generational ZGC and Beyond

The use-case

Hazelcast Jet はインメモリ分散バッチ/ストリーム処理エンジンです【1】。前述の一連のブログでは、異なるセットアップとベンチマークを使っていくつかの異なる実験を実施していました。私が再作成したものはパート3のもので、異なるレベルのスループットにおける高いパーセンタイルのレイテンシーに焦点を当てています。

Performance of Modern Java on Data-Heavy Workloads: The Low-Latency Rematch
https://jet-start.sh/blog/2020/06/23/jdk-gc-benchmarks-rematch

彼らの実験と同じ種類のハードウェアで実行しているわけではないので、今回の結果をブログに記載の実験結果と比較できませんが、JDK 21を使用したレガシーZGCの結果は、彼らの実験結果と非常に類似しています。また、今回のベンチマーク環境に合わせてベンチマークを少し修正し、インスツルメンテーションも追加しましたが、いずれも結果には影響しません。ベンチマークは相変わらず単一ノードで実行し、イベントレートは固定で、スループット/割り当てレートをキーセットに異なるサイズを使用することで変化させています。

The results

最初の実験が行われたJDK 14では、ある時点までZGCは素晴らしいパフォーマンスを見せていましたが、アロケーション・レートが高くなりすぎて、より悪いケースのレイテンシが長くなり始めました。Generational ZGCでこの状況がどのように変えることができるかを見てみましょう。

JDK 21

以前の実行と非常に類似しています。単一世代ZGCは低負荷の下では非常によく機能するものの、アロケーションの圧力が高くなるにつれて、より悪いケースのレイテンシが大きくなっています。対してGenerational ZGCでは、そのような振る舞いはありません。高負荷時でもp99.99のレイテンシーは非常に低いままです。

このレイテンシの改善の大きな理由は、Generation ZGCを使用すると、アプリケーショ ンスレッドがユーザーリクエストを処理するためにより頻繁に利用可能になるためです。ZGCは完全なconcurrent GCです。これはつまり、アプリケーションスレッドがオブジェクトの再配置によりZGCを助けなければならない場合がある、ということです。これは、アプリケーションがオブジェクトを使用する前に、ZGC自身のスレッドがオブジェクトの再配置を終えていない場合に発生します(再配置の作業はアプリケーションコードからは見えません)。レガシーZGCのスレッドはヒープ全体を処理する必要があるため、アプリケーションのスレッドは、「本当の」作業の代わりに再配置作業を行い、かなり頻繁に手助けをする必要があります。対照的に、Generational ZGCのスレッドはほとんどの場合、ヒープの一部(young generation)だけを処理すればよいため、再配置が必要なオブジェクトの数はほとんどなく、アプリケーション・スレッドが再配置を手伝う可能性は低くなります。

Generational ZGCがレガシーZGCと比較してなぜこれほど良い結果を得ている理由についてより詳細な説明をお望みなら、私のP99confのプレゼンテーションをご覧ください。

Reducing P99 Latencies with Generational ZGC
https://inside.java/2023/10/21/reducing-p99-latencies-with-genzgc/

P99 CONF 2023 | Reducing P99 Latencies with Generational ZGC by Stefan Johansson

その中で、私はHazelcast Jetベンチマークでコード分析し、違いがどこにあるのか、パフォーマンスに大きく影響する理由をより理解できるように説明しています。

Try it out and give us feedback

このエントリを読んで、Generational ZGCを試してみようと思ったのではないでしょうか。JDK 21を入手して、アプリケーションを以下の2個のフラグをつけて実行してみてください。

OpenJDK JDK 21.0.1 GA Release
https://jdk.java.net/21/

-XX:+UseZGC -XX:+ZGenerational

2つ目のフラグは、Generational ZGCを有効にするために重要なものです。長期的なゴールはZGCの世代別バージョンだけにすることで、そのためにユーザーからのフィードバックを得たいと考えています。Generational ZGCがレガシーZGCほどうまく動作していないユースケースがあれば、以下のOpenJDKメーリングリストを使ってお知らせください。

hotspot-gc-use — Technical discussion of usage of the HotSpot garbage collectors
https://mail.openjdk.org/mailman/listinfo/hotspot-gc-use

OracleのJavaチームからの他の一般的なニュースや洞察については、必ずinside.javaをチェックしてください。

Inside.java
https://inside.java


【1】https://github.com/hazelcast/hazelcast-jet 

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください