06
Demo 06 — Low-Latency JVM: G1GC vs ZGC
Quarkus 3.33.1 / Java 21
⏱ ~10 min
Run this demo
View source on GitHub ↗
cd quarkus-demo-06-latency
chmod +x demo.sh
./demo.sh
Two identical Quarkus apps, same heap, same load. One G1GC, one ZGC. The GC pause delta (not throughput) is the metric that matters for SLAs.
UBI9 default GC
ubi9/openjdk-21-runtime ships Shenandoah by default. This demo overrides it explicitly:
JAVA_OPTS: "-XX:+UseG1GC" # container 1
JAVA_OPTS: "-XX:+UseZGC -XX:+ZGenerational" # container 2
ZGC throughput caveat
ZGC uses a load barrier — fires on every object read — adding ~5-15% constant overhead. In the hey load test, ZGC shows lower throughput than G1GC. This is expected and correct. The meaningful metric is the GC pause delta in Steps 4-5.
GC decision guide
| Collector | Pause | Choose when |
|---|---|---|
| Shenandoah | 1–20ms | UBI9 default — already this without any config |
| ZGC | < 1ms | p99 SLA tighter than 10ms, or heap > 32GB |
| G1GC | 50–300ms | Throughput-oriented, non-latency-sensitive |