diff --git a/frameworks/wtx-http2/Cargo.lock b/frameworks/wtx-http2/Cargo.lock index a5bc81be..4c5b92f8 100644 --- a/frameworks/wtx-http2/Cargo.lock +++ b/frameworks/wtx-http2/Cargo.lock @@ -217,9 +217,9 @@ dependencies = [ [[package]] name = "wtx" -version = "0.44.2" +version = "0.44.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97e63d7c2604cca7d683a4692c5254a48c83e9a178f1f42e329c4fc337b5a00" +checksum = "7dc1cd886098559ac89f0ae62a440d828caf32b98b7890f22d9de41b68a37625" dependencies = [ "foldhash", "hashbrown", @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "wtx-macros" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cddfb3e929d853956742aff20d58874899f6fa2a645cece1a34d5ce822414cb3" +checksum = "c0878e9e0fbf13ba57967eac090f5c4793e19e496c89c413e5dbdf58fad7054f" dependencies = [ "proc-macro2", "quote", diff --git a/frameworks/wtx-http2/src/main.rs b/frameworks/wtx-http2/src/main.rs index 1c43de79..9e6c1805 100644 --- a/frameworks/wtx-http2/src/main.rs +++ b/frameworks/wtx-http2/src/main.rs @@ -3,13 +3,12 @@ use wtx::{ codec::i64_string, collection::{ArrayVectorU8, Vector}, http::{ - Header, KnownHeaderName, ReqResBuffer, StatusCode, + Header, HttpRecvParams, KnownHeaderName, ReqResBuffer, StatusCode, server_framework::{ JsonReply, PathOwned, Router, ServerFrameworkBuilder, State, VerbatimParams, get, }, }, misc::Wrapper, - rng::{ChaCha20, CryptoSeedableRng}, sync::Arc, }; @@ -23,21 +22,18 @@ async fn main() -> wtx::Result<()> { let dataset = load_dataset(); let router = Router::paths(wtx::paths!( ("/baseline2", get(endpoint_baseline2)), - ("/health", get(endpoint_health)), ("/json/{count}", get(endpoint_json)), ))?; - // HttpArena's baseline-h2c / json-h2c profiles run h2load against - // http://localhost:8082 with prior-knowledge h2c — no TLS. wtx's .tokio - // entrypoint routes through http2_tokio(), which speaks HTTP/2 cleartext - // from the connection preface and rejects HTTP/1.1 by construction. That - // satisfies validate.sh's anti-cheat: the h2c port must not dual-serve h1. - ServerFrameworkBuilder::new(ChaCha20::from_std_random()?, router) - .with_conn_aux(move |_| Ok(ConnAux { dataset: dataset.clone() })) + ServerFrameworkBuilder::new(HttpRecvParams::with_permissive_params(), router) + .with_conn_aux(move || Ok(ConnAux { dataset: dataset.clone() })) .tokio( "0.0.0.0:8082", |_error| {}, |_| Ok(()), - |_| Ok(()), + |stream| { + stream.set_nodelay(true)?; + Ok(()) + }, |_error| {}, ) .await @@ -46,53 +42,33 @@ async fn main() -> wtx::Result<()> { async fn endpoint_baseline2( state: State<'_, ConnAux, (), ReqResBuffer>, ) -> wtx::Result { - // h2load sends GET /baseline2?a=1&b=1 with empty body. Sum integer - // values from the query string; non-integer values silently skip - // (matches the reference nginx/h2o/actix contracts). let mut sum: i64 = 0; - for (_k, v) in state.req.rrd.uri.query_params() { - if let Ok(n) = v.parse::() { - sum = sum.wrapping_add(n); - } + for (_, value) in state.req.rrd.uri.query_params() { + sum = sum.wrapping_add(value.parse()?); } state.req.rrd.clear(); state.req.rrd.body.extend_from_copyable_slice(i64_string(sum).as_bytes())?; - state.req.rrd.headers.push_from_iter(Header::from_name_and_value( - KnownHeaderName::Server.into(), - ["wtx"], - ))?; - state.req.rrd.headers.push_from_iter(Header::from_name_and_value( - KnownHeaderName::ContentType.into(), - ["text/plain"], - ))?; + state.req.rrd.headers.push_from_iter_many([ + Header::from_name_and_value(KnownHeaderName::ContentType.into(), ["text/plain"].into_iter()), + Header::from_name_and_value(KnownHeaderName::Server.into(), ["wtx"].into_iter()) + ])?; Ok(VerbatimParams(StatusCode::Ok)) } -async fn endpoint_health() {} - async fn endpoint_json( state: State<'_, ConnAux, (), ReqResBuffer>, PathOwned(count): PathOwned, ) -> wtx::Result { - // Contract: GET /json/{count}?m={multiplier} - // - Take first `count` items from /data/dataset.json (clamped to len) - // - For each item, compute total = price × quantity × m - // - Serialize {items, count} as JSON per request (no cache — tuned - // rules in docs/test-profiles/h1/isolated/json-processing forbid - // pre-computed response caches). - let m: i64 = state - .req - .rrd - .uri - .query_params() - .find(|(k, _)| *k == "m") - .and_then(|(_, v)| v.parse().ok()) - .unwrap_or(1); + let mut m: f64 = 1.0; + for (key, value) in state.req.rrd.uri.query_params() { + if key != "m" { + continue; + } + m = f64::from(value.parse::()?); + break; + } let dataset_len = state.conn_aux.dataset.len(); let clamped = if count > dataset_len { dataset_len } else { count }; - let m_f = m as f64; - // Drop the request headers/body before composing the response so client - // request headers (user-agent, accept, …) don't echo back to the caller. state.req.rrd.clear(); let items = state.conn_aux.dataset.iter().take(clamped).map(move |el| { Ok(ProcessedItem { @@ -104,15 +80,13 @@ async fn endpoint_json( active: el.active, tags: ArrayVectorU8::from_iterator(el.tags.iter().map(|el| el.as_str()))?, rating: RatingOut { score: el.rating.score, count: el.rating.count }, - total: el.price * (el.quantity as f64) * m_f, + total: el.price * el.quantity * m, }) }); let resp = JsonResponse { count: clamped, items: Wrapper(items) }; serde_json::to_writer(&mut state.req.rrd.body, &resp).unwrap_or_default(); - state.req.rrd.headers.push_from_iter(Header::from_name_and_value( - KnownHeaderName::Server.into(), - ["wtx"], - ))?; + let header = Header::from_name_and_value(KnownHeaderName::Server.into(), ["wtx"]); + state.req.rrd.headers.push_from_iter(header)?; Ok(JsonReply(StatusCode::Ok)) } @@ -130,7 +104,7 @@ struct DatasetItem { name: String, category: String, price: f64, - quantity: i64, + quantity: f64, active: bool, tags: ArrayVectorU8, rating: Rating, @@ -153,7 +127,7 @@ struct ProcessedItem<'any> { name: &'any str, category: &'any str, price: f64, - quantity: i64, + quantity: f64, active: bool, tags: ArrayVectorU8<&'any str, 6>, rating: RatingOut, diff --git a/site/data/baseline-h2c-1024.json b/site/data/baseline-h2c-1024.json index da0196e1..de676684 100644 --- a/site/data/baseline-h2c-1024.json +++ b/site/data/baseline-h2c-1024.json @@ -78,18 +78,18 @@ { "framework": "wtx", "language": "Rust", - "rps": 651217, - "avg_latency": "117.30ms", - "p99_latency": "117.30ms", - "cpu": "4364.3%", - "memory": "1.4GiB", + "rps": 663592, + "avg_latency": "127.66ms", + "p99_latency": "127.66ms", + "cpu": "5459.2%", + "memory": "1.3GiB", "connections": 1024, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "22.68MB/s", + "bandwidth": "23.07MB/s", "reconnects": 0, - "status_2xx": 3301674, + "status_2xx": 3357780, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/baseline-h2c-256.json b/site/data/baseline-h2c-256.json index 7c0f4a77..1a1d0f3d 100644 --- a/site/data/baseline-h2c-256.json +++ b/site/data/baseline-h2c-256.json @@ -78,18 +78,18 @@ { "framework": "wtx", "language": "Rust", - "rps": 681334, - "avg_latency": "36.59ms", - "p99_latency": "36.59ms", - "cpu": "4593.7%", - "memory": "657MiB", + "rps": 658273, + "avg_latency": "37.88ms", + "p99_latency": "37.88ms", + "cpu": "4554.2%", + "memory": "605MiB", "connections": 256, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "23.54MB/s", + "bandwidth": "22.74MB/s", "reconnects": 0, - "status_2xx": 3427112, + "status_2xx": 3311118, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/baseline-h2c-4096.json b/site/data/baseline-h2c-4096.json index bd935882..47feb7d6 100644 --- a/site/data/baseline-h2c-4096.json +++ b/site/data/baseline-h2c-4096.json @@ -78,18 +78,18 @@ { "framework": "wtx", "language": "Rust", - "rps": 675669, - "avg_latency": "284.85ms", - "p99_latency": "284.85ms", - "cpu": "5253.3%", - "memory": "2.8GiB", + "rps": 638297, + "avg_latency": "322.51ms", + "p99_latency": "322.51ms", + "cpu": "4324.0%", + "memory": "2.4GiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "23.75MB/s", + "bandwidth": "22.44MB/s", "reconnects": 0, - "status_2xx": 3452670, + "status_2xx": 3261702, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/current.json b/site/data/current.json index 922f5c56..0cfbe928 100644 --- a/site/data/current.json +++ b/site/data/current.json @@ -10,7 +10,7 @@ "docker": "29.3.0", "docker_runtime": "runc", "governor": "performance", - "commit": "a69ab556", + "commit": "64013bfd", "tcp": { "lo_mtu": "1500", "congestion": "cubic", diff --git a/site/data/json-h2c-1024.json b/site/data/json-h2c-1024.json index a03824b1..3e257920 100644 --- a/site/data/json-h2c-1024.json +++ b/site/data/json-h2c-1024.json @@ -78,18 +78,18 @@ { "framework": "wtx", "language": "Rust", - "rps": 599466, - "avg_latency": "46.46ms", - "p99_latency": "46.46ms", - "cpu": "4670.1%", - "memory": "766MiB", + "rps": 640863, + "avg_latency": "43.80ms", + "p99_latency": "43.80ms", + "cpu": "4356.7%", + "memory": "614MiB", "connections": 1024, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "2.08GB/s", + "bandwidth": "2.24GB/s", "reconnects": 0, - "status_2xx": 3033298, + "status_2xx": 3236360, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/json-h2c-4096.json b/site/data/json-h2c-4096.json index d6089580..46a68795 100644 --- a/site/data/json-h2c-4096.json +++ b/site/data/json-h2c-4096.json @@ -78,18 +78,18 @@ { "framework": "wtx", "language": "Rust", - "rps": 575992, - "avg_latency": "142.43ms", - "p99_latency": "142.43ms", - "cpu": "4293.4%", - "memory": "1.8GiB", + "rps": 606637, + "avg_latency": "145.44ms", + "p99_latency": "145.44ms", + "cpu": "5294.6%", + "memory": "1.3GiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "2.01GB/s", + "bandwidth": "2.14GB/s", "reconnects": 0, - "status_2xx": 2937560, + "status_2xx": 3087786, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0