//! End-to-End Routing Latency Benchmark //! //! Measures complete request flow: //! - Client request → Auth pipeline → Backend proxy → Response //! - TARGET: <10μs total overhead (auth + proxying) //! //! Tests: //! 1. Auth overhead only (mock backend) //! 2. Proxy overhead only (no auth) //! 3. Full end-to-end (auth + proxy) //! 4. Different request sizes //! 5. Concurrent requests use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::runtime::Runtime; /// Mock backend service that responds immediately struct MockBackend { response_time_ns: u64, } impl MockBackend { fn new(response_time_ns: u64) -> Self { Self { response_time_ns } } async fn handle_request(&self, _request: &[u8]) -> Vec { // Simulate backend processing time if self.response_time_ns > 0 { tokio::time::sleep(Duration::from_nanos(self.response_time_ns)).await; } b"response_data".to_vec() } } /// Mock auth layer struct MockAuthLayer { overhead_ns: u64, } impl MockAuthLayer { fn new(overhead_ns: u64) -> Self { Self { overhead_ns } } async fn authenticate(&self, _token: &str) -> bool { // Simulate auth overhead if self.overhead_ns > 0 { tokio::time::sleep(Duration::from_nanos(self.overhead_ns)).await; } true } } /// Request router struct Router { auth: Arc, backend: Arc, } impl Router { fn new(auth_overhead_ns: u64, backend_response_ns: u64) -> Self { Self { auth: Arc::new(MockAuthLayer::new(auth_overhead_ns)), backend: Arc::new(MockBackend::new(backend_response_ns)), } } async fn route_request(&self, token: &str, request: &[u8]) -> Option> { // Authenticate if !self.auth.authenticate(token).await { return None; } // Forward to backend Some(self.backend.handle_request(request).await) } } /// Benchmark 1: Auth overhead only (backend responds instantly) fn bench_auth_only_overhead(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let router = Router::new(5_000, 0); // 5μs auth, instant backend c.bench_function("auth_overhead_only", |b| { b.iter(|| { rt.block_on(async { let result = router .route_request(black_box("valid-jwt-token"), black_box(b"request")) .await; black_box(result); }); }); }); } /// Benchmark 2: Proxy overhead only (no auth) fn bench_proxy_only_overhead(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let router = Router::new(0, 0); // No auth, instant backend c.bench_function("proxy_overhead_only", |b| { b.iter(|| { rt.block_on(async { let result = router .route_request(black_box("valid-jwt-token"), black_box(b"request")) .await; black_box(result); }); }); }); } /// Benchmark 3: Full end-to-end with realistic backend fn bench_end_to_end_realistic(c: &mut Criterion) { let rt = Runtime::new().unwrap(); // 8μs auth + 100μs backend (simulates actual service) let router = Router::new(8_000, 100_000); c.bench_function("end_to_end_realistic_backend", |b| { b.iter(|| { rt.block_on(async { let result = router .route_request(black_box("valid-jwt-token"), black_box(b"request")) .await; black_box(result); }); }); }); } /// Benchmark 4: Target performance (10μs total overhead) fn bench_target_performance(c: &mut Criterion) { let rt = Runtime::new().unwrap(); // 8μs auth + instant backend = <10μs total let router = Router::new(8_000, 0); c.bench_function("target_10us_overhead", |b| { b.iter(|| { rt.block_on(async { let result = router .route_request(black_box("valid-jwt-token"), black_box(b"request")) .await; black_box(result); }); }); }); } /// Benchmark 5: Different request sizes fn bench_request_sizes(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let router = Router::new(8_000, 0); // 8μs auth overhead let mut group = c.benchmark_group("request_size_impact"); for size in &[100, 1_000, 10_000, 100_000] { let request = vec![0u8; *size]; group.bench_with_input( BenchmarkId::new("request_routing", format!("{}B", size)), &request, |b, req| { b.iter(|| { rt.block_on(async { let result = router .route_request("valid-jwt-token", black_box(req)) .await; black_box(result); }); }); }, ); } group.finish(); } /// Benchmark 6: Concurrent request handling fn bench_concurrent_requests(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let router = Arc::new(Router::new(8_000, 0)); let mut group = c.benchmark_group("concurrent_requests"); for concurrency in &[1, 10, 100] { group.bench_with_input( BenchmarkId::new("parallel_routing", concurrency), concurrency, |b, &n| { b.iter(|| { rt.block_on(async { let mut handles = vec![]; let router_clone = router.clone(); for _ in 0..n { let router_ref = router_clone.clone(); let handle = tokio::spawn(async move { router_ref .route_request("valid-jwt-token", b"request") .await }); handles.push(handle); } for handle in handles { black_box(handle.await.unwrap()); } }); }); }, ); } group.finish(); } /// Benchmark 7: Failed auth fast-path fn bench_auth_failure_fast_path(c: &mut Criterion) { let rt = Runtime::new().unwrap(); // Custom router that fails auth immediately struct FastFailRouter { auth_overhead_ns: u64, } impl FastFailRouter { async fn route_request(&self, token: &str, _request: &[u8]) -> Option> { if self.auth_overhead_ns > 0 { tokio::time::sleep(Duration::from_nanos(self.auth_overhead_ns)).await; } // Simulate quick rejection (invalid JWT signature) if token.len() < 10 { return None; } None } } let router = FastFailRouter { auth_overhead_ns: 100, // 100ns for quick rejection }; c.bench_function("auth_failure_fast_path", |b| { b.iter(|| { rt.block_on(async { let result = router .route_request(black_box("invalid"), black_box(b"request")) .await; black_box(result); }); }); }); } /// Benchmark 8: Latency percentiles measurement fn bench_latency_percentiles(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let router = Router::new(8_000, 0); c.bench_function("latency_distribution", |b| { b.iter_custom(|iters| { let mut total = Duration::ZERO; for _ in 0..iters { let start = Instant::now(); rt.block_on(async { let result = router.route_request("valid-jwt-token", b"request").await; black_box(result); }); total += start.elapsed(); } total }); }); } criterion_group!( routing_benches, bench_auth_only_overhead, bench_proxy_only_overhead, bench_end_to_end_realistic, bench_target_performance, bench_request_sizes, bench_concurrent_requests, bench_auth_failure_fast_path, bench_latency_percentiles ); criterion_main!(routing_benches);