//! Criterion benchmark for the RuView streaming-engine hot path. //! //! The live system runs at 20 Hz → a **50 ms** wall-clock budget per cycle. //! This measures one full [`StreamingEngine::process_cycle`] (fuse + quality //! scoring + calibration provenance + privacy gate + WorldGraph semantic node) //! for a 4-node / 56-subcarrier mesh — the realistic ESP32-S3 HT20 case. use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use wifi_densepose_bfld::PrivacyMode; use wifi_densepose_engine::StreamingEngine; use wifi_densepose_geo::types::GeoRegistration; use wifi_densepose_signal::hardware_norm::{CanonicalCsiFrame, HardwareType}; use wifi_densepose_signal::ruvsense::fusion_quality::CalibrationId; use wifi_densepose_signal::ruvsense::MultiBandCsiFrame; fn node_frame(node_id: u8, ts_us: u64, n_sub: usize) -> MultiBandCsiFrame { MultiBandCsiFrame { node_id, timestamp_us: ts_us, channel_frames: vec![CanonicalCsiFrame { amplitude: (0..n_sub).map(|i| 1.0 + 0.1 * i as f32).collect(), phase: (0..n_sub).map(|i| i as f32 * 0.05).collect(), hardware_type: HardwareType::Esp32S3, }], frequencies_mhz: vec![2412], coherence: 0.9, } } fn bench_cycle(c: &mut Criterion) { let frames: Vec = (0..4).map(|i| node_frame(i, 1000 + u64::from(i), 56)).collect(); c.bench_function("process_cycle_4nodes_56sc", |b| { b.iter_batched( || { let mut e = StreamingEngine::new(PrivacyMode::PrivateHome, 1, GeoRegistration::default()); let room = e.add_room("living_room", "Living Room"); e.add_sensor("esp32-com9", room); (e, room) }, |(mut e, room)| { e.process_cycle(&frames, CalibrationId(1), room, 0).unwrap() }, BatchSize::SmallInput, ); }); } /// Mesh guard in isolation: cold build (node set appears) vs steady state /// (identical weights next cycle → change-gated, zero graph updates) for a /// 12-node mesh — the full ADR-029 deployment size. fn bench_mesh_guard(c: &mut Criterion) { use wifi_densepose_engine::MeshGuard; let nodes: Vec = (0..12).collect(); let w = |i: usize, j: usize| 0.4 + 0.01 * ((i + j) % 7) as f64; c.bench_function("mesh_guard_cold_build_12n", |b| { b.iter_batched( MeshGuard::default, |mut g| g.update(&nodes, w), BatchSize::SmallInput, ); }); c.bench_function("mesh_guard_steady_state_12n", |b| { let mut g = MeshGuard::default(); g.update(&nodes, w); // warm b.iter(|| g.update(&nodes, w)); }); c.bench_function("mesh_guard_one_edge_change_12n", |b| { let mut g = MeshGuard::default(); g.update(&nodes, w); let mut flip = false; b.iter(|| { flip = !flip; let delta = if flip { 0.2 } else { 0.0 }; g.update(&nodes, |i, j| { if (i.min(j), i.max(j)) == (0, 1) { 0.4 + delta } else { w(i, j) } }) }); }); } criterion_group!(benches, bench_cycle, bench_mesh_guard); criterion_main!(benches);