Spring Boot Webflux Native vs Rust frameworks: Performance comparison for hello world case

Mayank C
Tech Tonic

--

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!

--

--