Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
523 changes: 344 additions & 179 deletions frameworks/Rust/axum/Cargo.lock

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions frameworks/Rust/axum/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "axum-techempower"
version = "0.2.1"
version = "0.3.0"
authors = ["Dragos Varovici <[email protected]>"]
edition = "2021"
edition = "2024"

[[bin]]
name = "axum"
Expand Down Expand Up @@ -39,49 +39,49 @@ simd-json = [
]

[dependencies]
axum = { version = "0.7.9", default-features = false, features = [
axum = { version = "0.8.3", default-features = false, features = [
"json",
"query",
"http1",
"tokio",
] }
deadpool = { version = "0.12.1", features = ["rt_tokio_1", "serde", "managed"] }
deadpool = { version = "0.12.2", features = ["rt_tokio_1", "serde", "managed"] }
deadpool-postgres = { version = "0.14.1", features = ["rt_tokio_1", "serde"] }
dotenv = "0.15.0"
futures = "0.3.31"
futures-util = "0.3.31"
mongodb = { version = "3.1.1", features = [
mongodb = { version = "3.2.3", features = [
"zstd-compression",
"snappy-compression",
"zlib-compression",
] }
num_cpus = "1.16.0"
rand = { version = "0.8.5", features = ["small_rng"] }
serde = { version = "1.0.216", features = ["derive"] }
serde_json = "1.0.134"
sqlx = { version = "0.8.2", features = [
rand = { version = "0.9.0", features = ["small_rng"] }
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
sqlx = { version = "0.8.3", features = [
"postgres",
"macros",
"runtime-tokio",
"tls-rustls",
] }
tokio = { version = "1.42.0", features = ["full"] }
tokio = { version = "1.44.2", features = ["full"] }
tokio-pg-mapper = { version = "0.2.0" }
tokio-pg-mapper-derive = { version = "0.2.0" }
tokio-postgres = { version = "0.7.12" }
tokio-postgres = { version = "0.7.13" }
tower = { version = "0.5.2", features = ["util"] }
tower-http = { version = "0.6.2", features = ["set-header"] }
yarte = "0.15.7"
simd-json = { version = "0.14.3", optional = true }
axum-core = { version = "0.4.5", optional = true }
simd-json = { version = "0.15.0", optional = true }
axum-core = { version = "0.5.2", optional = true }
mime = { version = "0.3.17", optional = true }
bytes = { version = "1.9.0", optional = true }
serde_path_to_error = { version = "0.1.16", optional = true }
socket2 = "0.5.8"
hyper = { version = "1.5", features = ["server", "http1"] }
bytes = { version = "1.10.1", optional = true }
serde_path_to_error = { version = "0.1.17", optional = true }
socket2 = "0.5.9"
hyper = { version = "1.6", features = ["server", "http1"] }
hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1"] }
quick_cache = "0.6.9"
mimalloc = "0.1.43"
quick_cache = "0.6.12"
mimalloc = "0.1.45"


[profile.release]
Expand Down
3 changes: 1 addition & 2 deletions frameworks/Rust/axum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,4 @@ built with Tokio, Tower, and Hyper.
- Use of PostgreSQL prepared statements cache (where supported).
- Use of PostgreSQL arrays to execute multi-row database updates with a single `UPDATE` query.
- This is permitted by the [test requirements](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates), step (ix).
- More performance improvements are to be expected in version 0.8:
- https://github.com/tokio-rs/axum/issues/1827
- Use of a fast PRNG
2 changes: 1 addition & 1 deletion frameworks/Rust/axum/axum.dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM docker.io/rust:1.83-slim-bookworm AS builder
FROM docker.io/rust:1.86-slim-bookworm AS builder

RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config libssl-dev \
Expand Down
8 changes: 4 additions & 4 deletions frameworks/Rust/axum/src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{env, str::FromStr};

use core::fmt::Debug;
use rand::{distributions::Uniform, rngs::SmallRng, Rng};
use rand::{distr::Uniform, rngs::SmallRng, Rng, RngCore};
pub mod models;
pub mod utils;

Expand Down Expand Up @@ -36,14 +36,14 @@ where
/// Generate a single integer in the range 1 to 10,000 (inclusive)
#[allow(dead_code)]
#[inline(always)]
pub fn random_id(rng: &mut SmallRng) -> i32 {
rng.gen_range(1..10_001)
pub fn random_id(rng: &mut impl RngCore) -> i32 {
rng.random_range(1..=10_000)
}

/// Generate an iterator of integers in the range 1 to 10,000 (inclusive)
#[allow(dead_code)]
#[inline(always)]
pub fn random_ids(rng: &mut SmallRng, count: usize) -> impl Iterator<Item = i32> + use<'_> {
rng.sample_iter(Uniform::new(1, 10_001))
rng.sample_iter(Uniform::new_inclusive(1, 10_000).unwrap())
.take(count)
}
10 changes: 4 additions & 6 deletions frameworks/Rust/axum/src/main_mongo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use mongodb::{
options::{ClientOptions, Compressor},
Client,
};
use rand::{rngs::SmallRng, thread_rng, Rng, SeedableRng};
use rand::{rngs::SmallRng, rng, SeedableRng};
use yarte::Template;
use mimalloc::MiMalloc;

Expand All @@ -43,9 +43,7 @@ pub struct FortunesTemplate<'a> {
}

async fn db(DatabaseConnection(db): DatabaseConnection) -> impl IntoResponse {
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();

let random_id = (rng.gen::<u32>() % 10_000 + 1) as i32;
let random_id = random_id(&mut rng());

let world = find_world_by_id(db, random_id)
.await
Expand All @@ -60,7 +58,7 @@ async fn queries(
) -> impl IntoResponse {
let q = parse_params(params);

let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());
let worlds = find_worlds(db, &mut rng, q).await;
let results = worlds.expect("worlds could not be retrieved");

Expand All @@ -73,7 +71,7 @@ async fn updates(
) -> impl IntoResponse {
let q = parse_params(params);

let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());

let worlds = find_worlds(db.clone(), &mut rng, q)
.await
Expand Down
10 changes: 4 additions & 6 deletions frameworks/Rust/axum/src/main_mongo_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,10 @@ use mongodb::{
options::{ClientOptions, Compressor},
Client,
};
use rand::{rngs::SmallRng, thread_rng, SeedableRng};
use rand::{rngs::SmallRng, rng, SeedableRng};

async fn db(DatabaseConnection(db): DatabaseConnection) -> impl IntoResponse {
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();

let random_id = random_id(&mut rng);
let random_id = random_id(&mut rng());

let world = find_world_by_id(db, random_id)
.await
Expand All @@ -52,7 +50,7 @@ async fn queries(
) -> impl IntoResponse {
let q = parse_params(params);

let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());
let worlds = find_worlds(db, &mut rng, q).await;
let results = worlds.expect("worlds could not be retrieved");

Expand All @@ -65,7 +63,7 @@ async fn updates(
) -> impl IntoResponse {
let q = parse_params(params);

let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());

let worlds = find_worlds(db.clone(), &mut rng, q)
.await
Expand Down
7 changes: 3 additions & 4 deletions frameworks/Rust/axum/src/main_pg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use axum::{
extract::Query, http::StatusCode, response::IntoResponse, routing::get, Router,
};
use dotenv::dotenv;
use rand::{rngs::SmallRng, thread_rng, SeedableRng};
use rand::rng;
use yarte::Template;
use mimalloc::MiMalloc;

Expand Down Expand Up @@ -33,10 +33,9 @@ pub struct FortunesTemplate<'a> {
}

async fn db(DatabaseConnection(conn): DatabaseConnection) -> impl IntoResponse {
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();

let id = random_id(&mut rng());
let world = conn
.fetch_world_by_id(random_id(&mut rng))
.fetch_world_by_id(id)
.await
.expect("error loading world");

Expand Down
9 changes: 4 additions & 5 deletions frameworks/Rust/axum/src/main_pg_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use common::simd_json::Json;
use common::{random_ids, SELECT_ALL_FORTUNES, SELECT_WORLD_BY_ID, UPDATE_WORLDS};
use dotenv::dotenv;
use futures_util::{stream::FuturesUnordered, TryStreamExt};
use rand::{rngs::SmallRng, thread_rng, SeedableRng};
use rand::{rngs::SmallRng, rng, SeedableRng};
use yarte::Template;
use mimalloc::MiMalloc;

Expand All @@ -38,8 +38,7 @@ pub struct FortunesTemplate<'a> {
}

async fn db(DatabaseClient(client): DatabaseClient) -> impl IntoResponse {
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let random_id = random_id(&mut rng);
let random_id = random_id(&mut rng());

let select = &client.prepare_cached(SELECT_WORLD_BY_ID).await.unwrap();
let world = fetch_world_by_id(&client, random_id, select)
Expand All @@ -55,7 +54,7 @@ async fn queries(
) -> impl IntoResponse {
let q = parse_params(params);

let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());
let select = &client.prepare_cached(SELECT_WORLD_BY_ID).await.unwrap();
let future_worlds = FuturesUnordered::new();

Expand Down Expand Up @@ -98,7 +97,7 @@ async fn updates(
) -> impl IntoResponse {
let q = parse_params(params);

let mut rng = SmallRng::from_entropy();
let mut rng = SmallRng::from_rng(&mut rng());
let select = &client.prepare_cached(SELECT_WORLD_BY_ID).await.unwrap();
let update = &client.prepare_cached(UPDATE_WORLDS).await.unwrap();

Expand Down
11 changes: 5 additions & 6 deletions frameworks/Rust/axum/src/main_sqlx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use axum::{
};
use dotenv::dotenv;
use quick_cache::sync::Cache;
use rand::{rngs::SmallRng, thread_rng, SeedableRng};
use rand::{rngs::SmallRng, rng, SeedableRng};
use sqlx::models::World;
use yarte::Template;
use mimalloc::MiMalloc;
Expand Down Expand Up @@ -42,10 +42,9 @@ pub struct FortunesTemplate<'a> {
}

async fn db(State(AppState { db, .. }): State<AppState>) -> impl IntoResponse {
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();

let id = random_id(&mut rng());
let world: World = ::sqlx::query_as(common::SELECT_WORLD_BY_ID)
.bind(random_id(&mut rng))
.bind(id)
.fetch_one(&mut *db.acquire().await.unwrap())
.await
.expect("error loading world");
Expand All @@ -57,7 +56,7 @@ async fn queries(
State(AppState { db, .. }): State<AppState>,
Query(params): Query<Params>,
) -> impl IntoResponse {
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());
let count = parse_params(params);
let mut worlds: Vec<World> = Vec::with_capacity(count);

Expand Down Expand Up @@ -100,7 +99,7 @@ async fn cache(
Query(params): Query<Params>,
) -> impl IntoResponse {
let count = parse_params(params);
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());
let mut worlds: Vec<Option<World>> = Vec::with_capacity(count);

for id in random_ids(&mut rng, count) {
Expand Down
3 changes: 1 addition & 2 deletions frameworks/Rust/axum/src/mongo/database.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{convert::Infallible, io};

use axum::{async_trait, extract::FromRequestParts, http::request::Parts};
use axum::{extract::FromRequestParts, http::request::Parts};
use futures_util::{stream::FuturesUnordered, StreamExt, TryStreamExt};
use mongodb::{bson::doc, Database};
use rand::rngs::SmallRng;
Expand All @@ -9,7 +9,6 @@ use crate::common::{models::{Fortune, World}, random_ids};

pub struct DatabaseConnection(pub Database);

#[async_trait]
impl FromRequestParts<Database> for DatabaseConnection {
type Rejection = Infallible;

Expand Down
3 changes: 1 addition & 2 deletions frameworks/Rust/axum/src/mongo_raw/database.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{convert::Infallible, io};

use axum::{async_trait, extract::FromRequestParts, http::request::Parts};
use axum::{extract::FromRequestParts, http::request::Parts};
use futures_util::{stream::FuturesUnordered, TryStreamExt};
use mongodb::{
bson::{doc, RawDocumentBuf},
Expand All @@ -12,7 +12,6 @@ use crate::common::{models::World, random_ids};

pub struct DatabaseConnection(pub Database);

#[async_trait]
impl FromRequestParts<Database> for DatabaseConnection {
type Rejection = Infallible;

Expand Down
9 changes: 4 additions & 5 deletions frameworks/Rust/axum/src/pg/database.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{convert::Infallible, io, sync::Arc};

use axum::{async_trait, extract::FromRequestParts, http::request::Parts};
use axum::{extract::FromRequestParts, http::request::Parts};
use futures::{stream::futures_unordered::FuturesUnordered, StreamExt, TryStreamExt};
use rand::{rngs::SmallRng, thread_rng, SeedableRng};
use rand::{rngs::SmallRng, rng, SeedableRng};
use tokio::pin;
use tokio_postgres::{connect, Client, NoTls, Statement};

Expand Down Expand Up @@ -78,7 +78,7 @@ impl PgConnection {
}

pub async fn fetch_random_worlds(&self, num: usize) -> Result<Vec<World>, PgError> {
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());

let futures = FuturesUnordered::new();

Expand All @@ -93,7 +93,7 @@ impl PgConnection {
let mut worlds = self.fetch_random_worlds(num).await?;

// Update the worlds with new random numbers
let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap();
let mut rng = SmallRng::from_rng(&mut rng());
let mut ids = Vec::with_capacity(num);
let mut nids = Vec::with_capacity(num);

Expand Down Expand Up @@ -139,7 +139,6 @@ impl PgConnection {

pub struct DatabaseConnection(pub Arc<PgConnection>);

#[async_trait]
impl FromRequestParts<Arc<PgConnection>> for DatabaseConnection {
type Rejection = Infallible;

Expand Down
2 changes: 0 additions & 2 deletions frameworks/Rust/axum/src/pg_pool/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
pg_pool::models::{Fortune, World},
};
use axum::{
async_trait,
extract::FromRequestParts,
http::{request::Parts, StatusCode},
};
Expand Down Expand Up @@ -55,7 +54,6 @@ pub async fn create_pool(

pub struct DatabaseClient(pub Client);

#[async_trait]
impl FromRequestParts<deadpool_postgres::Pool> for DatabaseClient {
type Rejection = (StatusCode, String);

Expand Down
2 changes: 1 addition & 1 deletion frameworks/Rust/axum/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn set_socket_options(addr: SocketAddr) -> io::Result<tokio::net::TcpListener> {
}

/// Build an Axum server with consistent configuration, using the high-level API exposed
/// by Axum 0.7. This is intended for convenience and intentionally does not provide much
/// by Axum 0.8. This is intended for convenience and intentionally does not provide much
/// customisability.
#[allow(dead_code)]
pub async fn serve(app: Router<()>, port: Option<u16>) {
Expand Down
Loading