How Virtual Threads Boost Spring Boot 3 Performance: Real-World Benchmarks

This article demonstrates how Spring Boot 3.2.5 leverages JDK 21 virtual threads to improve asynchronous request handling, comparing platform‑thread and virtual‑thread performance with JMeter, exploring thread‑pool configurations, database access tests, and providing practical code examples and tuning tips.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How Virtual Threads Boost Spring Boot 3 Performance: Real-World Benchmarks

Environment

Spring Boot 3.2.5 + JDK 21

1. Introduction

JDK 21 introduces virtual threads; Spring Boot 3.2.x supports them for asynchronous tasks and requests. This article compares platform threads and virtual threads using JMeter to evaluate performance.

2. Practical Cases

2.1 Simulated Time‑Consuming Operation

A controller method returns a Callable that sleeps for two seconds.

// Spring MVC controller using Callable
@GetMapping("/platform")
public Callable<Object> platform() {
    System.out.printf("Request start: %d%n", System.currentTimeMillis());
    Callable<Object> callable = () -> {
        System.out.printf("Current thread: %s%n", Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(2);
        return "Callable task completed";
    };
    System.out.printf("Request end: %d%n", System.currentTimeMillis());
    return callable;
}

Browser test shows the Tomcat thread finishes instantly while the Callable runs on another thread.

Performance Test Setup

All tests use JVM options -Xms1g -Xmx1g and JMeter with 500 concurrent users, 10 loops, targeting the above endpoint.

Platform thread (default pool, core size 8) shows many timeouts and low throughput.

Increasing the task executor core size to 200 improves throughput but competes with Tomcat threads for CPU and memory.

Virtual Thread Configuration

Enable virtual threads with:

spring:
  threads:
    virtual:
      enabled: true

Spring MVC async uses a bean named applicationTaskExecutor. With virtual threads enabled and no custom pool, throughput rises dramatically:

Remote call example:

@GetMapping("/http")
public Callable<Object> http() {
    System.out.printf("Request start: %d%n", System.currentTimeMillis());
    Callable<Object> callable = () -> {
        System.out.printf("Current thread: %s%n", Thread.currentThread().getName());
        return new RestTemplate().getForObject("http://localhost:8088/demos/rr", String.class);
    };
    System.out.printf("Request end: %d%n", System.currentTimeMillis());
    return callable;
}

2.2 Database‑Based Test

Repository for counting rows:

public interface BigTableRepository extends JpaRepository<BigTable, Integer> {
    // Count total rows
    @Query("select count(name) from BigTable e")
    long count();
}

Data source configured with HikariCP (minimumIdle 200, maximumPoolSize 200):

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/batch?serverTimezone=GMT%2B8&useSSL=false
    username: root
    password: xxxooo
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimumIdle: 200
      maximumPoolSize: 200

Platform thread tests with core sizes 8, 100, 200 show little change in overall throughput.

Virtual thread test shows a significant drop in throughput.

Virtual threads can dramatically increase application throughput when the workload involves thousands of concurrent tasks that spend most of their time waiting, rather than being CPU‑bound.

Additional Virtual Thread Tuning

Limit concurrency with:

spring:
  task:
    execution:
      simple:
        concurrency-limit: 100

Default limit is -1 (no limit).

Conclusion: Virtual threads provide higher throughput for I/O‑bound asynchronous requests, but well‑tuned platform thread pools may still be competitive, especially for database‑heavy workloads.

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.

Performance TestingSpring BootJMeterVirtual ThreadsAsync Requests
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

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.