Companion module for the rewritten post 'Virtual Threads on Spring Boot 4.1: The Benchmarks, Re-Run, and the Pinning Advice That Expired', retitled and re-benchmarked on Boot 4.1.1 / JDK 25.0.4.1 (the original post was written against Boot 3.4 / JDK 21). Covers: I/O-bound and CPU-bound throughput (platform vs virtual threads, including a JIT-warmup benchmarking bug this build caught and fixed), JEP 491 proof that synchronized no longer pins a virtual thread's carrier across a blocking call as of JDK 24 (obsoleting the old avoid-synchronized advice), proof that -Djdk.tracePinnedThreads=full is inert on JDK 25, and JEP 506's finalized ScopedValue API (JDK 25 GA, no --enable-preview, and a different shape than the old preview API). Kept as its own module rather than a new top-level repository, alongside the existing async/ module, which already has a stronger dual-JDK JEP 491 proof that this module's docs cross-link to instead of duplicating.
44 lines
2.4 KiB
Markdown
44 lines
2.4 KiB
Markdown
# 1. Enabling virtual threads on Spring Boot 4.1
|
|
|
|
[README](../README.md) | Next: [02-benchmark-methodology.md](02-benchmark-methodology.md)
|
|
|
|
Source: [`application.yml`](../src/main/resources/application.yml), [`DemoController.java`](../src/main/java/com/ankurm/vthreads/DemoController.java).
|
|
Test: [`ThreadTypeTest.java`](../src/test/java/com/ankurm/vthreads/ThreadTypeTest.java).
|
|
Transcript: [`docs/output/00-thread-type-confirmation.txt`](output/00-thread-type-confirmation.txt).
|
|
|
|
## Still one property
|
|
|
|
`spring.threads.virtual.enabled=true` is unchanged since Boot 3.2 and still the whole
|
|
configuration surface for most apps on Boot 4.1. It requires JDK 21+; this repo runs it on
|
|
JDK 25.
|
|
|
|
## What actually flips
|
|
|
|
Confirmed against a real running embedded server, not by reading the reference docs:
|
|
|
|
```
|
|
enabled=false -> Thread: Thread[#9711,http-nio-auto-5-exec-1,5,main] | Virtual: false
|
|
enabled=true -> Thread: VirtualThread[#9737,tomcat-handler-0]/runnable@ForkJoinPool-1-worker-2 | Virtual: true
|
|
```
|
|
|
|
The platform-thread name prefix changed between the Boot 3 era and this repo's Boot 4.1 run
|
|
(`http-nio-auto-5-exec-1` here vs. the `http-nio-8080-exec-3` shape in the older post) because
|
|
this test binds to `server.port=0` (a random port) rather than a fixed 8080 -- Tomcat's
|
|
connector-name-derived thread prefix reflects that. Cosmetic, but worth not being surprised by
|
|
if your own logs look different from either example.
|
|
|
|
## Test infrastructure trap worth knowing about
|
|
|
|
Setting the property via `SpringApplicationBuilder.properties(...)` and expecting it to win
|
|
over `application.yml` is a real bug this repo hit while building the benchmark below:
|
|
`.properties(...)` binds to Spring's **`defaultProperties`** source, which has the *lowest*
|
|
precedence of any property source Spring Boot recognizes -- lower than `application.yml`,
|
|
which had `spring.threads.virtual.enabled: false` as its own explicit default. The fix was
|
|
passing it as a command-line-style argument to `run(...)` instead
|
|
(`"--spring.threads.virtual.enabled=" + value`), which binds at the highest precedence. See
|
|
[`LoadBenchmarkTest.java`](../src/test/java/com/ankurm/vthreads/LoadBenchmarkTest.java) for
|
|
where this was caught -- the first draft of the CPU-bound benchmark below silently ran both
|
|
scenarios on platform threads and reported a difference that didn't exist.
|
|
|
|
Next: [02-benchmark-methodology.md](02-benchmark-methodology.md).
|