#![allow(dead_code)] //! Throughput Benchmark - Concurrent Authenticated Requests //! //! Measures maximum requests per second: //! - TARGET: >100,000 req/s single-threaded //! - Multi-threaded scaling //! - Different authentication workloads //! - Realistic traffic patterns use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::runtime::Runtime; /// Lightweight auth simulator struct AuthSimulator { success_rate: f64, counter: Arc, } impl AuthSimulator { fn new(success_rate: f64) -> Self { Self { success_rate, counter: Arc::new(AtomicU64::new(0)), } } async fn authenticate(&self, _request_id: u64) -> bool { let count = self.counter.fetch_add(1, Ordering::Relaxed); // Simulate success rate (count as f64 / 100.0) % 1.0 < self.success_rate } fn requests_processed(&self) -> u64 { self.counter.load(Ordering::Relaxed) } } /// Request handler struct RequestHandler { auth: Arc, } impl RequestHandler { fn new(auth: Arc) -> Self { Self { auth } } async fn handle_request(&self, request_id: u64) -> bool { self.auth.authenticate(request_id).await } } /// Benchmark 1: Single-threaded throughput (TARGET: >100K req/s) fn bench_single_threaded_throughput(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let auth = Arc::new(AuthSimulator::new(0.95)); // 95% success rate let handler = RequestHandler::new(auth.clone()); let mut group = c.benchmark_group("single_threaded_throughput"); group.throughput(Throughput::Elements(1)); group.bench_function("100k_req_target", |b| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { for i in 0..iters { black_box(handler.handle_request(i).await); } }); start.elapsed() }); }); group.finish(); } /// Benchmark 2: Multi-threaded throughput fn bench_multi_threaded_throughput(c: &mut Criterion) { let mut group = c.benchmark_group("multi_threaded_throughput"); for num_threads in &[1, 2, 4, 8, 16] { let rt = tokio::runtime::Builder::new_multi_thread() .worker_threads(*num_threads) .build() .unwrap(); let auth = Arc::new(AuthSimulator::new(0.95)); let handler = Arc::new(RequestHandler::new(auth.clone())); group.throughput(Throughput::Elements(1000)); group.bench_with_input( BenchmarkId::new("concurrent_requests", num_threads), num_threads, |b, &threads| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { let mut handles = vec![]; let requests_per_thread = iters / threads as u64; for _ in 0..threads { let handler_clone = handler.clone(); let handle = tokio::spawn(async move { for i in 0..requests_per_thread { black_box(handler_clone.handle_request(i).await); } }); handles.push(handle); } for handle in handles { handle.await.unwrap(); } }); start.elapsed() }); }, ); } group.finish(); } /// Benchmark 3: Different success rates fn bench_success_rate_impact(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let mut group = c.benchmark_group("success_rate_impact"); for success_rate in &[0.5, 0.8, 0.95, 0.99, 1.0] { let auth = Arc::new(AuthSimulator::new(*success_rate)); let handler = RequestHandler::new(auth.clone()); group.throughput(Throughput::Elements(1000)); group.bench_with_input( BenchmarkId::new("throughput", format!("{}%", (success_rate * 100.0) as u32)), success_rate, |b, _rate| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { for i in 0..iters { black_box(handler.handle_request(i).await); } }); start.elapsed() }); }, ); } group.finish(); } /// Benchmark 4: Burst traffic patterns fn bench_burst_patterns(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let auth = Arc::new(AuthSimulator::new(0.95)); let handler = Arc::new(RequestHandler::new(auth.clone())); let mut group = c.benchmark_group("burst_patterns"); // Constant load group.bench_function("constant_load_1000_req", |b| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { for i in 0..iters.min(1000) { black_box(handler.handle_request(i).await); } }); start.elapsed() }); }); // Burst pattern: All at once group.bench_function("burst_1000_concurrent", |b| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { let mut handles = vec![]; for i in 0..iters.min(1000) { let handler_clone = handler.clone(); let handle = tokio::spawn(async move { handler_clone.handle_request(i).await }); handles.push(handle); } for handle in handles { black_box(handle.await.unwrap()); } }); start.elapsed() }); }); group.finish(); } /// Benchmark 5: Request size impact on throughput fn bench_request_size_throughput(c: &mut Criterion) { let rt = Runtime::new().unwrap(); struct RequestProcessor { auth: Arc, } impl RequestProcessor { async fn process(&self, _data: &[u8]) -> bool { self.auth.authenticate(0).await } } let auth = Arc::new(AuthSimulator::new(0.95)); let processor = RequestProcessor { auth: auth.clone() }; let mut group = c.benchmark_group("request_size_throughput"); for size in &[100, 1_000, 10_000, 100_000] { let data = vec![0u8; *size]; group.throughput(Throughput::Bytes(*size as u64)); group.bench_with_input( BenchmarkId::new("process_request", format!("{}B", size)), &data, |b, request_data| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { for _ in 0..iters { black_box(processor.process(request_data).await); } }); start.elapsed() }); }, ); } group.finish(); } /// Benchmark 6: Sustained throughput over time fn bench_sustained_throughput(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let auth = Arc::new(AuthSimulator::new(0.95)); let handler = RequestHandler::new(auth.clone()); c.bench_function("sustained_1_second", |b| { b.iter_custom(|_iters| { let start = Instant::now(); let mut count = 0u64; rt.block_on(async { let end_time = Instant::now() + Duration::from_secs(1); while Instant::now() < end_time { black_box(handler.handle_request(count).await); count += 1; } }); let elapsed = start.elapsed(); let rps = count as f64 / elapsed.as_secs_f64(); println!("Sustained throughput: {:.0} req/s", rps); elapsed }); }); } /// Benchmark 7: Request rate limits fn bench_rate_limited_throughput(c: &mut Criterion) { let rt = Runtime::new().unwrap(); struct RateLimitedHandler { auth: Arc, limit: AtomicU64, max_rps: u64, } impl RateLimitedHandler { fn new(auth: Arc, max_rps: u64) -> Self { Self { auth, limit: AtomicU64::new(0), max_rps, } } async fn handle(&self, request_id: u64) -> bool { let count = self.limit.fetch_add(1, Ordering::Relaxed); if count >= self.max_rps { return false; // Rate limited } self.auth.authenticate(request_id).await } } let mut group = c.benchmark_group("rate_limited_throughput"); for limit in &[1_000, 10_000, 100_000] { let auth = Arc::new(AuthSimulator::new(0.95)); let handler = RateLimitedHandler::new(auth.clone(), *limit); group.bench_with_input(BenchmarkId::new("max_rps", limit), limit, |b, _| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { for i in 0..iters { black_box(handler.handle(i).await); } }); start.elapsed() }); }); } group.finish(); } /// Benchmark 8: HFT scenario (TARGET: 100K req/s minimum) fn bench_hft_scenario(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let auth = Arc::new(AuthSimulator::new(0.99)); // 99% success (HFT quality) let handler = RequestHandler::new(auth.clone()); let mut group = c.benchmark_group("hft_scenario"); group.throughput(Throughput::Elements(100_000)); group.bench_function("hft_100k_target", |b| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { for i in 0..iters { black_box(handler.handle_request(i).await); } }); let elapsed = start.elapsed(); // Calculate actual throughput let rps = iters as f64 / elapsed.as_secs_f64(); if rps < 100_000.0 { println!("⚠️ Below target: {:.0} req/s (target: 100K)", rps); } else { println!("✓ Target met: {:.0} req/s", rps); } elapsed }); }); group.finish(); } /// Benchmark 9: Latency under load fn bench_latency_under_load(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let auth = Arc::new(AuthSimulator::new(0.95)); let handler = Arc::new(RequestHandler::new(auth.clone())); let mut group = c.benchmark_group("latency_under_load"); for load in &[100, 1_000, 10_000, 100_000] { group.bench_with_input( BenchmarkId::new("requests_in_flight", load), load, |b, &n| { b.iter_custom(|_iters| { let start = Instant::now(); rt.block_on(async { let mut handles = vec![]; for i in 0..n { let handler_clone = handler.clone(); let handle = tokio::spawn(async move { handler_clone.handle_request(i).await }); handles.push(handle); } for handle in handles { black_box(handle.await.unwrap()); } }); start.elapsed() }); }, ); } group.finish(); } /// Benchmark 10: Request batching efficiency fn bench_batching_efficiency(c: &mut Criterion) { let rt = Runtime::new().unwrap(); let auth = Arc::new(AuthSimulator::new(0.95)); let handler = Arc::new(RequestHandler::new(auth.clone())); let mut group = c.benchmark_group("batching_efficiency"); for batch_size in &[1, 10, 100, 1000] { group.throughput(Throughput::Elements(*batch_size as u64)); group.bench_with_input( BenchmarkId::new("batch_processing", batch_size), batch_size, |b, &n| { b.iter_custom(|iters| { let start = Instant::now(); rt.block_on(async { for batch in 0..(iters / n as u64) { let mut handles = vec![]; for i in 0..n { let handler_clone = handler.clone(); let request_id = batch * n as u64 + i as u64; let handle = tokio::spawn(async move { handler_clone.handle_request(request_id).await }); handles.push(handle); } for handle in handles { black_box(handle.await.unwrap()); } } }); start.elapsed() }); }, ); } group.finish(); } criterion_group!( throughput_benches, bench_single_threaded_throughput, bench_multi_threaded_throughput, bench_success_rate_impact, bench_burst_patterns, bench_request_size_throughput, bench_sustained_throughput, bench_rate_limited_throughput, bench_hft_scenario, bench_latency_under_load, bench_batching_efficiency ); criterion_main!(throughput_benches);