Spring Boot Webflux Native vs Rust frameworks: Performance comparison for hello world case
This is a requested article.
Numerous people have requested to compare Spring Boot Webflux 3.2 running natively (image built using graal) vs popular frameworks on the Rust side (Actix, Axum, Rocket, and Warp).
Here it is. This article compares Spring Boot Webflux 3.2 native with the four most popular frameworks on the Rust side.
Note: This isn’t really an apple to apple comparison. Neither of the Rust frameworks provide even a fraction of the extensive features provided by Spring Boot ecosystem. We’ll still compare them because of the reader’s interest.
Test setup
All tests are executed on MacBook Pro M2 with 16G RAM & 8+4 CPU cores. The load tester is Bombardier (Written in Go). The software versions are:
- Java 21 Graal CE
- Spring Boot Webflux 3.2
- Rust 1.75.0
The application code is as follows:
Java
application.properties
server.port=3000
spring.threads.virtual.enabled=true
Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.reactivestreams.Publisher;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import reactor.core.publisher.Mono;
@SpringBootApplication
@EnableWebFlux
@EnableAsync
@Controller
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class);
}
@GetMapping("/")
@ResponseBody
public Publisher<String> handler() {
return Mono.just("Hello world!");
}
}
Rust
Actix
cargo.toml
[package]
name = "hello_world_actix"
version = "0.1.0"
edition = "2021"
[dependencies]
actix-web = "4.4.1"
main.rs
use actix_web::{get, App, HttpServer, Responder};
#[get("/")]
async fn index() -> impl Responder {
"Hello World!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(index))
.bind(("127.0.0.1", 3000))?
.run()
.await
}
Axum
cargo.toml
[package]
name = "axum_hello_world"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.7.3"
hyper = { version = "1.1.0", features = ["full"] }
tokio = { version = "1.35.1", features = ["full"] }
tower = "0.4.13"
main.rs
use axum::{
routing::get,
Router,
};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(|| async { "Hello World!" }));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
Rocket
cargo.toml
[package]
name = "rocket_hello_world"
version = "0.1.0"
edition = "2021"
[dependencies]
rocket = "=0.5.0"
main.rs
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello world!"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
Warp
cargo.toml
[package]
name = "warp_hello_world"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1.35.1", features = ["full"] }
warp = "0.3"
main.rs
use warp::Filter;
#[tokio::main]
async fn main() {
let routes = warp::path::end().map(|| "Hello World!");
warp::serve(routes)
.run(([127, 0, 0, 1], 3000))
.await;
}
NOTE: All the rust code has been built in RELEASE mode
Results
Each test consists of running 5M for 100, and 300 concurrent connections.
The results in chart form are as follows:
Time taken & RPS
Latencies
Resource usage
Impressions
As mentioned at the start of this article, this isn’t an apple to apple comparison. Spring Boot’s feature set is way too big for Actix/Axum/Rocket/Warp to match.
Nevertheless, Spring’s reactive arm in native code gives a tough competition to Rust’s frameworks. There isn’t any noticeable difference in RPS and latencies.
However, Spring Boot webflux’s resource usage is significantly higher than Rust. The CPU usage is high, but memory usage is comparatively very high. Rust’s memory usage is almost nothing.
Thanks for reading this article!