bench-scenarios/examples/dataplane_bench.rs
//! The request-path bench driver — W12's before/after table.
//!
//! Runs the four `dataplane` arms against in-process gateways on loopback and
//! prints one table. Dev-only (plan ?8). Knobs are environment variables so a
//! run is one command with no argument parser in the library:
//!
//! - `HOLGER_BENCH_LARGE_MB` (1024): the large blob.
//! - `HOLGER_BENCH_SMALL_OPS` (2000..20000 from the scale): 4 KiB ops.
//! - `HOLGER_BENCH_OCI_MB` (256): the OCI blob.
//! - `HOLGER_BENCH_GRPC_STREAM_MB` (32) / `HOLGER_BENCH_GRPC_STREAMS` (8).
//! - `HOLGER_BENCH_ARMS`: comma list of `large,small,grpc,oci,digest` (default all).
use anyhow::Result;
use holger_bench_scenarios::{dataplane, grpc_door, Scale};
fn mib(b: u64) -> f64 {
b as f64 / 1_048_576.0
}
fn main() -> Result<()> {
let scale = Scale::from_env();
let arms: Vec<String> = std::env::var("HOLGER_BENCH_ARMS")
.unwrap_or_else(|_| "large,small,grpc,oci,digest".into())
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
let want = |a: &str| arms.iter().any(|x| x == a);
println!("| arm | MB/s | ops/s | p999 ms | server RSS growth | RSS/byte |");
println!("|---|---|---|---|---|---|");
if want("large") {
let o = dataplane::http_large(&scale)?;
println!(
"| HTTP PUT {} MiB (raw) | {:.0} | {:.2} | — | {:.1} MiB | {:.3} |",
mib(o.bytes as u64),
o.put.mb_per_sec,
o.put.ops_sec,
mib(o.rss_growth_put),
o.rss_per_byte_put
);
println!(
"| HTTP GET {} MiB (raw) | {:.0} | {:.2} | — | {:.1} MiB | {:.3} |",
mib(o.bytes as u64),
o.get.mb_per_sec,
o.get.ops_sec,
mib(o.rss_growth_get),
o.rss_per_byte_get
);
}
if want("small") {
let o = dataplane::http_small(&scale)?;
println!(
"| HTTP PUT 4 KiB ×{} (raw) | {:.1} | {:.0} | {:.2} (p50 {:.3}, p99 {:.2}) | — | — |",
o.ops, o.put.mb_per_sec, o.put.ops_sec, o.put_p999_ms, o.put_p50_ms, o.put_p99_ms
);
println!(
"| HTTP GET 4 KiB ×{} (raw) | {:.1} | {:.0} | {:.2} (p50 {:.3}, p99 {:.2}) | — | — |",
o.ops, o.get.mb_per_sec, o.get.ops_sec, o.get_p999_ms, o.get_p50_ms, o.get_p99_ms
);
}
if want("grpc") {
let o = grpc_door::grpc_fetch_stream(&scale)?;
println!(
"| gRPC StreamArtifact {} MiB ×{} | {:.0} | {:.2} | {:.1} | {:.1} MiB | {:.3} |",
mib(o.artifact_bytes as u64),
o.artifacts,
o.t.mb_per_sec,
o.t.ops_sec,
o.p999_ms,
mib(o.rss_growth_large),
o.rss_bytes_per_artifact_byte
);
}
if want("digest") {
let o = dataplane::digest_throughput(&scale)?;
println!(
"| blake3 {} MiB serial (request thread) | {:.0} | — | — | — | — |",
mib(o.bytes as u64),
o.serial_mbs
);
println!(
"| blake3 {} MiB on gatling | {:.0} | — | — | — | {:.2}x |",
mib(o.bytes as u64),
o.gatling_mbs,
o.speedup
);
}
if want("oci") {
let o = dataplane::oci_chunked(&scale)?;
println!(
"| OCI chunked push {} MiB ({} PATCH) | {:.0} | {:.2} | finalize {:.0} ms | {:.1} MiB (finalize) | {:.3} |",
mib(o.bytes as u64), o.chunks, o.push.mb_per_sec, o.push.ops_sec,
o.finalize.as_secs_f64() * 1000.0, mib(o.rss_growth_finalize), o.rss_per_byte_finalize
);
}
Ok(())
}