Skip to content
This repository was archived by the owner on Mar 24, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
25 changes: 22 additions & 3 deletions frameworks/Rust/water-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ edition = "2024"

[dependencies]
askama = "0.14.0"
tokio = { version = "1.47.1", features = ["full"] }
water_http = { features = ["use_io_uring","use_only_http1"],optional = true , version = "3.4.2-beta.4" }
tokio = { version = "1.48.0", features = ["full"] }

water_http = { features = ["use_only_http1"],optional = true , version = "4.0.1-beta.89",git = "https://github.com/HassanSharara/water_http", rev = "78c9859"}
#water_http_unrealistic = {package = "water_http" ,features = ["use_io_uring","use_only_http1"],optional = true , version = "3.4.2-beta.4" }

smallvec = "1.15.1"
nanorand = "0.8.0"
tokio-postgres = "0.7.15"
Expand All @@ -19,6 +22,12 @@ httpdate = "1.0.3"
parking_lot = "0.12.5"
yarte = { version = "0.15.7" ,features = ["bytes-buf", "json"] }
itoa = {version = "1.0.15" ,optional = true}
smallbox = "0.8.8"
mimalloc = "0.1.48"
xitca-postgres = "0.4.0"
#chopin-pg = "0.5.18"
water_buffer = {version = "1.2.9",features = ["bytes","unsafe_clone"]}
integer_to_bytes = "0.2.2"


[[bin]]
Expand All @@ -42,4 +51,14 @@ required-features = ["cache"]
json_plaintext = ["water_http"]
db = ["water_http/thread_shared_struct"]
cache = ["water_http/thread_shared_struct","itoa"]
all = ["water_http/thread_shared_struct"]
all = ["water_http","water_http/thread_shared_struct","water_http/cpu_affinity"]
uring = ["water_http","water_http/thread_shared_struct", "water_http/use_io_uring"]

[profile.release]
opt-level = 3
codegen-units = 1
panic = 'abort'
lto = "fat"
debug = false
incremental = false
overflow-checks = false
48 changes: 45 additions & 3 deletions frameworks/Rust/water-http/benchmark_config.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@

{
"framework": "water-http",
"maintainers" : ["HassanSharara"],
"tests": [
{
"default": {
"default": {
"json_url": "/json",
"plaintext_url": "/plaintext",
"fortune_url": "/fortunes",
"db_url": "/db",
"query_url": "/queries?q=",
"update_url": "/updates?q=",
"cached_query_url": "/cached-queries?q=",
"port": 8080,
"approach": "Stripped",
"classification": "Fullstack",
Expand All @@ -25,6 +23,50 @@
"database_os": "Linux",
"display_name": "water_http",
"tags": []
},



"unstable": {
"json_url": "/json",
"plaintext_url": "/plaintext",
"fortune_url": "/fortunes",
"db_url": "/db",
"query_url": "/queries?q=",
"update_url": "/updates?q=",
"port": 8080,
"approach": "Realistic",
Comment thread
msmith-techempower marked this conversation as resolved.
"classification": "Fullstack",
"database": "Postgres",
"framework": "water_http",
"language": "Rust",
"orm": "raw",
"platform": "Rust",
"webserver": "water_http",
"os": "Linux",
"database_os": "Linux",
"display_name": "water_http [uns]"
},

"uring": {
"json_url": "/json",
"plaintext_url": "/plaintext",
"fortune_url": "/fortunes",
"db_url": "/db",
"query_url": "/queries?q=",
"update_url": "/updates?q=",
"port": 8080,
"approach": "Realistic",
Comment thread
msmith-techempower marked this conversation as resolved.
"classification": "Fullstack",
"database": "Postgres",
"framework": "water_http",
"language": "Rust",
"orm": "raw",
"platform": "Rust",
"webserver": "water_http",
"os": "Linux",
"database_os": "Linux",
"display_name": "water_http [io-uring]"
}
}
]
Expand Down
104 changes: 104 additions & 0 deletions frameworks/Rust/water-http/src/buf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use std::cell::RefCell;
use crate::models::Fortune;
// Assuming water_buffer crate exists
// use water_buffer::WaterBuffer as BM;

// Mocking the type for compilation demo
type WaterBuffer = Vec<u8>;

const INITIAL_VEC_CAPACITY: usize = 128;
const DEFAULT_SIZE: usize = 4048;
const MAX_BUFFER_SIZE: usize = 8192; // Allow some growth before discarding
const MAX_CACHED_BUFFERS: usize = 117; // Set to your test requirement

thread_local! {
static BUFFER_CACHE: RefCell<Vec<WaterBuffer>> = RefCell::new(Vec::with_capacity(INITIAL_VEC_CAPACITY));
static FORTUNE_CACHE: RefCell<Vec<Vec<Fortune>>> = RefCell::new(Vec::with_capacity(INITIAL_VEC_CAPACITY));
}

pub struct PooledBuffer {
inner: Option<WaterBuffer>,
}

pub struct FortunesPool {
inner: Option<Vec<Fortune>>,
}


impl PooledBuffer {
pub fn new() -> Self {
Self::with_capacity(DEFAULT_SIZE)
}

pub fn with_capacity(cap: usize) -> Self {
let buf = BUFFER_CACHE.with(|cache| {
let mut cache = cache.borrow_mut();
if let Some(mut existing_buf) = cache.pop() {
// Assuming your WaterBuffer has a clear/reset method
existing_buf.clear();
existing_buf
} else {
// Fallback to new allocation if cache is empty
WaterBuffer::with_capacity(cap)
}
});

Self { inner: Some(buf) }
}

pub fn take_inner(&mut self) -> WaterBuffer {
self.inner.take().expect("Buffer already taken or dropped")
}

pub fn recycle(buf: WaterBuffer) {
// Use capacity() check to ensure we don't cache
// a buffer that grew to a massive size during one specific request
if buf.capacity() <= MAX_BUFFER_SIZE {
BUFFER_CACHE.with(|cache| {
let mut cache = cache.borrow_mut();
if cache.len() < MAX_CACHED_BUFFERS {
cache.push(buf);
}
});
}
}
}
impl FortunesPool {
pub fn new() -> Self {
Self::with_capacity(16)
}

pub fn with_capacity(cap: usize) -> Self {
let buf = FORTUNE_CACHE.with(|cache| {
let mut cache = cache.borrow_mut();
if let Some(mut existing_buf) = cache.pop() {
// Assuming your WaterBuffer has a clear/reset method
existing_buf.clear();
existing_buf
} else {
// Fallback to new allocation if cache is empty
Vec::with_capacity(cap)
}
});

Self { inner: Some(buf) }
}

pub fn take_inner(&mut self) -> Vec<Fortune> {
self.inner.take().expect("Buffer already taken or dropped")
}

pub fn recycle(buf: WaterBuffer) {
// Use capacity() check to ensure we don't cache
// a buffer that grew to a massive size during one specific request
if buf.capacity() <= 16 {
BUFFER_CACHE.with(|cache| {
let mut cache = cache.borrow_mut();
if cache.len() < 2000 {
cache.push(buf);
}
});
}
}
}

2 changes: 2 additions & 0 deletions frameworks/Rust/water-http/src/cached.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#![allow(static_mut_refs)]


use std::io;
use std::fmt::Arguments;
use std::io::Write;
Expand Down
32 changes: 32 additions & 0 deletions frameworks/Rust/water-http/src/date.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::cell::UnsafeCell;
use std::time::{SystemTime, UNIX_EPOCH};

thread_local! {
// We store the bytes directly in the Thread Local Storage (TLS)
// to ensure the reference stays valid for the life of the thread.
static CACHED_DATE: UnsafeCell<(u64, [u8; 29])> = UnsafeCell::new((0, [0u8; 29]));
}

#[inline(always)]
pub fn get_date_fast() -> &'static str {
CACHED_DATE.with(|cell| {
unsafe {
let cache = &mut *cell.get();
// 1. Use a fast duration check
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_unchecked() // Benchmark trick: avoid panic branches
.as_secs();

if now != cache.0 {
cache.0 = now;
let date_str = httpdate::fmt_http_date(SystemTime::now());
cache.1.copy_from_slice(date_str.as_bytes());
}

// 2. Return a reference to the TLS memory directly.
// This is safe because the thread never dies during the benchmark.
std::str::from_utf8_unchecked(&cache.1)
}
})
}
Loading
Loading