How fast is it to build a static file server with Spring Boot 3.2 virtual thread?

Spring Boot 3.2 was released to great fanfare in November 2023, marking a pivotal moment in the world of Java development. This groundbreaking release introduces a host of revolutionary features, including:

  • Virtual Threads: Unleash scalability with Project Loom's virtual threads, reducing resource consumption and enhancing concurrency.
  • Native Image support: Build extremely fast applications with Native Image compilation, reducing startup time and optimizing resource utilization.
  • JVM Checkpoints: Leverage the CRaC project's JVM checkpoint mechanism to enable rapid restart of applications without lengthy re-initialization.
  • RestClient: Use the functional methods of the new RestClient interface to simplify HTTP interactions and simplify code.
  • Spring for Apache Pulsar: Leverage the power of Apache Pulsar for powerful messaging capabilities that are seamlessly integrated into your Spring Boot applications.

Among them, virtual threads are one of the most transformative features introduced in recent versions of Java. As the official documentation states: Virtual threads are lightweight threads that reduce the effort of writing, maintaining, and debugging high-throughput concurrent applications. A thread is the smallest unit of processing that can be scheduled. It operates concurrently with, and to a large extent independent of, other such units. It is an instance of java.lang.Thread. There are two types of threads: platform threads and virtual threads. Platform threads are implemented as thin wrappers for operating system (OS) threads. Platform threads run Java code on their underlying operating system threads, and platform threads capture the platform thread's operating system thread throughout its lifetime. Therefore, the number of available platform threads is limited to the number of operating system threads. Like platform threads, virtual threads are instances of java.lang.Thread. However, virtual threads are not bound to specific operating system threads. Virtual threads still run code on operating system threads. However, when code running in a virtual thread calls a blocking I/O operation, the Java runtime suspends the virtual thread until it can resume. The operating system thread associated with the suspended virtual thread is now free to perform operations on other virtual threads. Virtual threads are suitable for running tasks that are blocked most of the time, usually waiting for I/O operations to complete. However, they are not suitable for long-running, CPU-intensive operations.

While virtual threads are generally believed to perform well in I/O-intensive scenarios, their performance in CPU-intensive tasks remains a question mark. This series of articles takes a deep dive into the potential benefits of virtual threads in a variety of use cases, from basic "hello world" to static file serving (I/O intensive), QR code generation (CPU intensive), and multipart/form data real-world applications such as processing (mixed workloads).

In the opening article of this series, we looked at the performance of virtual threads compared to physical threads in the simplest (and impractical) hello world case. There is virtually no performance or resource usage difference between physical threads and virtual threads. In this article we will be more "practical" and compare for the static file server situation. This is definitely a common and "real world" case. Let's see what we found this time.

If you are upgrading from Spring Boot 2.3 to Spring 3.2, here is the upgrade guide from Spring Boot 2.x to 3.2 .

test environment

All tests were performed on a MacBook Pro M2 equipped with 16G RAM, 8 physical cores and 4 efficiency cores. The testing tool is Bombardier, one of the faster HTTP load testers (written in Go).

The software version is:

  • Java v21.0.1
  • Spring Boot 3.2.1

Program configuration

There is no need to write any Java files other than the main Java class, the static file server can only function through configuration.

application.propertiesThe files are as follows:

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

When using virtual threads, we will enable them by adding the following lines:

spring.threads.virtual.enabled=true

pom.xmlcontent:

<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

100K files with exactly the same size but different data are placed in the static resources directory. Each file size is exactly 102400 bytes.

Files can be named in the range 1 to 100000.

Use a modified version of Bombardier to generate a random request URL for each run:http://localhost:3000/static/<file-name>

Application scenarios

To ensure consistent results, each test goes through a 5K request warm-up phase before starting data collection.

Measurements were then carefully recorded across different ranges of concurrent connection levels (50, 100, and 300), each subject to a 5 million request workload.

Outcome evaluation

In addition to simply tracking raw speed, we will employ a detailed metrics framework to capture latency distribution (minimum, percentile, maximum) and throughput (requests per second).

Resource usage monitoring of CPU and memory will complement this analysis, providing a comprehensive understanding of system performance under different workloads.

Test Results

The results are presented in chart form as follows:

Summarize

Analysis of static file serving showed that physical threads were slightly better in terms of performance and resource efficiency (contrary to our expectations).

However, this I/O-bound scenario may not be the ideal place to exploit the full potential of virtual threads. Tasks involving database interaction may reveal more compelling advantages. Maybe the load isn't enough for the virtual threads to do their best work. To find out, we’ll cover URL shortening (database driven), QR code generation (CPU bound), and mixed workload scenarios (like form data processing) in the following articles, aiming to reveal where virtual threads really excel case.

Welcome to follow my public account: Programmer DD. Be the first to understand cutting-edge industry news, share in-depth technical information, and obtain high-quality learning resources

Bilibili crashed twice, Tencent’s “3.29” first-level accident... Taking stock of the top ten downtime accidents in 2023 Vue 3.4 “Slam Dunk” released MySQL 5.7, Moqu, Li Tiaotiao… Taking stock of the “stop” in 2023 More” (open source) projects and websites look back on the IDE of 30 years ago: only TUI, bright background color... Vim 9.1 is released, dedicated to Bram Moolenaar, the father of Redis, "Rapid Review" LLM Programming: Omniscient and Omnipotent&& Stupid "Post-Open Source "The era has come: the license has expired and cannot serve the general public. China Unicom Broadband suddenly limited the upload speed, and a large number of users complained. Windows executives promised improvements: Make the Start Menu great again. Niklaus Wirth, the father of Pascal, passed away.
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/didispace/blog/10584578