Files
asmhatreandClaude Sonnet 5.5 df13a904d7 Add jdk28-zgc: ZGC startup and warmup baseline on JDK 25/27/28-ea, and a probe for JEP 545/546
Spring Boot 4.1.1 harness measuring first-response time versus initial heap size and a
20,000-request warmup. Shows -XX:+ZAdaptiveHeapSizing is not yet in any build.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WzVQ6zFh9cuLPj9RSbRH8U
2026-10-12 17:13:14 +00:00

79 lines
3.7 KiB
Markdown

# jdk28-zgc — what ZGC startup and heap sizing look like today, and what JEP 545 / 546 propose
Companion module for the ankurm.com post
**ZGC in JDK 28: Adaptive Heap Sizing (JEP 546) and Faster Startup (JEP 545)**.
There is no `docs/` folder: this README and the captured files in [`output/`](output) are the documentation.
## The honest status
On 12 October 2026 both JEPs show **"Proposed to Target"** for release 28 on openjdk.org. Neither is integrated.
[`output/01-flag-probe.txt`](output/01-flag-probe.txt) proves it: `-XX:+ZAdaptiveHeapSizing` is an
*Unrecognized VM option* on JDK 25.0.4.1, Temurin 27+35 and OpenJDK 28-ea+19.
So this module does **not** benchmark the proposed features. It measures the baseline they are meant to improve,
on three JDKs, so you can rerun it the day a build contains the flag.
## Versions
| Component | Version |
|---|---|
| JDK 25 | Temurin 25.0.4.1+1 (LTS) |
| JDK 27 | Temurin 27+35 (GA 2026-09-15) |
| JDK 28 | OpenJDK 28-ea+19 (jdk.java.net build 19, 2026-10-08) |
| Spring Boot | 4.1.1 (`spring-boot-starter-webmvc`) |
| Machine | 2 vCPU, 8 GB RAM Linux sandbox (a small box: absolute numbers are illustrative) |
## Quick start
```console
mvn -B -DskipTests package # build with any JDK 25+
export J25=/path/to/jdk-25 J27=/path/to/jdk-27 J28=/path/to/jdk-28-ea
scripts/run-all.sh # regenerates everything in output/
RUNS=10 scripts/run-all.sh # more runs, tighter medians
scripts/startup.sh $J28 "my label" 5 -XX:+UseZGC -Xms1g
```
## Files
| File | What it is |
|---|---|
| [`src/main/java/com/ankurm/zgc/DemoApplication.java`](src/main/java/com/ankurm/zgc/DemoApplication.java) | One server: `/hello` allocates 16 KB, `/heap` reports committed and max heap |
| [`scripts/startup.sh`](scripts/startup.sh) | Wall-clock ms from process start to first HTTP 200, repeated, with min/median/max |
| [`scripts/warmup.sh`](scripts/warmup.sh) + [`scripts/Warmup.java`](scripts/Warmup.java) | 20,000 requests, 4 threads, timing each batch of 2,000; client is always JDK 25 |
| [`scripts/run-all.sh`](scripts/run-all.sh) | Runs all three experiments |
## Results (median of 5 runs, milliseconds to first response)
| Config | JDK 25 | JDK 27 | JDK 28-ea |
|---|---|---|---|
| ZGC defaults | 3439 | 3421 | 3420 |
| `-Xms64m` | 3299 | 3276 | 3350 |
| `-Xms1g` | 3478 | 3275 | 3642 |
| `-Xms3g` | 3836 | 3618 | 3803 |
| `-Xms3g -XX:+AlwaysPreTouch` | 4834 | 4560 | 5010 |
Raw per-run lines: [`output/02-startup-vs-xms.txt`](output/02-startup-vs-xms.txt).
Warmup, total ms for the first 20,000 requests (first 2,000 in brackets):
| Config | JDK 25 | JDK 28-ea |
|---|---|---|
| defaults | 9708 (2678) | 9912 (2567) |
| `-Xms3g` | 9193 (2606) | 9608 (2431) |
| `-Xms64m` | 9247 (2442) | 9893 (2590) |
Raw: [`output/03-warmup.txt`](output/03-warmup.txt).
## What the numbers say, and do not say
- A bigger initial heap costs startup time, and `AlwaysPreTouch` costs the most (about +1.2 s to +1.6 s on a 3 GB heap here).
- On this small box the effect is a fraction of Spring Boot's own ~3.3 s startup. JEP 545 describes a much larger effect on big heaps
(about 0.1 s at 2 MB versus over 10 s at 32 GB). This machine cannot reproduce that, and these numbers do not test it.
- The first batch of 2,000 requests takes about 2.4 to 2.7 s in every configuration, so for this app warmup is dominated by JIT and class loading, not heap growth.
- Under ZGC, `InitialHeapSize` ergonomics are 98,566,144 bytes on JDK 25 but 8,388,608 bytes on JDK 27 and 28-ea
([`output/01-flag-probe.txt`](output/01-flag-probe.txt)). I did not find which change causes that, so the post reports it as an observation only.
- Timings drift between runs. Treat them as indicative, not as a result.
## Licence
MIT, as the parent repository.