How Fast Are Virtual Threads in Spring Boot 3.2 for Static File Servers?

This article evaluates the performance of Spring Boot 3.2's virtual threads when serving static files, comparing them with traditional platform threads across various concurrency levels, and concludes that platform threads slightly outperform virtual threads in this I/O‑bound scenario while suggesting better use cases for database‑driven workloads.

Programmer DD
Programmer DD
Programmer DD
How Fast Are Virtual Threads in Spring Boot 3.2 for Static File Servers?

Previously I shared several articles about Java 21 and Spring Boot 3.2 involving virtual threads, as well as a comprehensive upgrade guide from Spring Boot 2.x to 3.2. Like many developers, I wanted to know how virtual threads could seamlessly boost program performance and in which scenarios they are effective.

Yesterday I saw a performance test that used Spring Boot 3.2 virtual threads to build a static file server, so I’m sharing the details here.

Spring Boot 3.2, released in November 2023, introduced a series of revolutionary features:

Virtual threads: leverage Project Loom to improve scalability, reduce resource consumption, and enhance concurrency.

Native Image support: compile to native binaries for ultra‑fast startup and lower resource usage.

JVM checkpoints: use the CRaC project to enable rapid application restarts without full re‑initialisation.

RestClient: a new interface that simplifies HTTP interactions and code.

Spring for Apache Pulsar: integrate powerful messaging capabilities directly into Spring Boot applications.

Virtual threads are one of the most transformative features in recent Java releases. According to the official documentation, they are lightweight threads that reduce the effort required to write, maintain, and debug high‑throughput concurrent applications. A thread is the smallest schedulable unit of execution. There are two types: platform threads and virtual threads. Platform threads are thin wrappers around OS threads; their number is limited by the operating system. Virtual threads are also instances of java.lang.Thread but are not bound to a specific OS thread. When a virtual thread performs a blocking I/O operation, the runtime suspends the virtual thread while the underlying OS thread can serve other virtual threads. Virtual threads excel at tasks that spend most of their time blocked on I/O, but they are not suited for long‑running CPU‑intensive work.

Although virtual threads are widely believed to shine in I/O‑intensive scenarios, their performance on CPU‑bound tasks remains uncertain. This series explores their potential advantages across use cases ranging from a simple "hello world" to static file serving (I/O‑bound), QR‑code generation (CPU‑bound), and multipart/form data handling (mixed workload).

In the earlier article we saw that physical threads and virtual threads performed almost identically in a trivial hello‑world benchmark. In this article we take a more practical approach by comparing them in a static file server—a common real‑world case.

Test Environment

All tests were run on a MacBook Pro M2 with 16 GB RAM, 8 physical cores and 4 efficiency cores. The load‑testing tool was Bombardier, a fast HTTP benchmarker written in Go.

Software versions:

Java v21.0.1

Spring Boot 3.2.1

Application Configuration

No additional Java source files are required; the static file server works purely via configuration.

The application.properties file:

server.port=3000
spring.mvc.static-path-pattern=/static/**
spring.web.resources.static-locations=file:/Users/mayankc/Work/source/perfComparisons/static/

To enable virtual threads, add the following line: spring.threads.virtual.enabled=true The pom.xml content:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.1</version>
    <relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
    <java.version>21</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Test Data

One hundred thousand 100 KB files (exactly 102 400 bytes each) were placed in the static resources directory, named from 1 to 100 000.

A modified version of Bombardier generated random request URLs for each run, e.g. http://localhost:3000/static/<file-name>.

Application Scenario

Each test began with a 5 K request warm‑up phase to ensure consistent results.

Measurements were then recorded at concurrency levels of 50, 100, and 300 connections, each handling a workload of 5 million requests.

Result Evaluation

Beyond raw throughput, we captured latency distribution (min, percentiles, max) and requests‑per‑second. CPU and memory usage were also monitored to provide a comprehensive view of system performance under varying loads.

Test Results

Results are presented in the following charts:

Conclusion

The analysis of the static file service shows that platform threads slightly outperform virtual threads in terms of performance and resource efficiency, contrary to our expectations.

However, this I/O‑bound scenario may not be ideal for showcasing the strengths of virtual threads. Tasks involving database interactions could reveal more compelling advantages, and the current load might be insufficient for virtual threads to demonstrate their full potential. Future articles will explore URL short‑link (database‑driven), QR‑code generation (CPU‑bound), and mixed‑workload scenarios such as multipart form handling to uncover cases where virtual threads truly excel.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootVirtual ThreadsJava 21Static File Server
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.