This project provides an advanced integration between Java Virtual Threads (Project Loom) and Netty's event loop, enabling seamless execution of blocking operations within the Netty event loop itself. Unlike standard approaches, which require offloading blocking tasks to external thread pools (incurring multiple thread hand-offs), this scheduler allows blocking code to run directly on the event loop's carrier thread, leveraging the virtual thread execution model.
In traditional Netty applications, blocking operations (e.g., JDBC, file I/O) must not run on the event loop. The usual workaround is:
- Offload the blocking task to an external thread pool (often using the default virtual thread scheduler).
- Once complete, hand control back to the Netty event loop to continue processing (e.g., send a response).
This process involves at least two thread hand-offs, which not only increases latency and complexity, but also wastes CPU cycles due to waking up both the external thread pool and the event loop again. Additionally, moving data between threads harms cache locality, reducing cache friendliness and overall performance.
- The Netty event loop runs as a special, long-lived virtual thread.
- Blocking operations issued from the event loop are executed as continuations, scheduled to run on the same platform thread (the "carrier")—unless work-stealing occurs (not implemented at the moment).
- Any virtual thread created from the event loop will, by default, run on the same carrier platform thread (again, unless work-stealing is introduced).
- This enables blocking libraries to be used transparently, without extra thread pools or hand-offs.
Aspect | Standard Netty + Loom (Default) | Netty with VirtualThread Scheduler (This Project) |
---|---|---|
Blocking Operation | Offloaded to external thread pool | Runs as continuation on event loop carrier |
Thread Hand-offs | 2+ | 0 |
Cache Friendliness | Poor (data moves between threads) | High (data stays on carrier thread) |
CPU Wakeups | More (wakes both pools) | Fewer (single carrier thread) |
Standard Netty + Loom (Default):
┌──────────────┐ offload ┌────────────────────────────┐ callback ┌──────────────┐
│ EventLoop │───────────▶│ Virtual Thread (Scheduler) │────────────▶│ EventLoop │
│ (OS Thread) │ │ (External Thread Pool) │ │ (OS Thread) │
└──────────────┘ └────────────────────────────┘ └──────────────┘
Netty with VirtualThread Scheduler:
┌────────────────────────────────────────────┐
│ Platform Thread (Carrier) │
│ ┌──────────────────────────────────────┐ │
│ │ EventLoop (Virtual Thread) │ │
│ │ (runs on carrier platform thread) │ │
│ │ ──────────────────────────────── │ │
│ │ Blocking Operation │ │
│ │ (Continuation, same platform) │ │
│ └──────────────────────────────────────┘ │
└────────────────────────────────────────────┘
This project uses Maven for build and dependency management.
- Build the project:
mvn clean install
- Run Benchmarks:
cd benchmarks mvn clean install java -jar target/benchmarks.jar
- Java 21 or newer (with Loom support)
- Maven 3.6+
For more details, see the source code and benchmark results in the respective modules.