wifi-densepose/v2/crates/wifi-densepose-engine/benches/engine_cycle.rs

89 lines
3.2 KiB
Rust

//! 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<MultiBandCsiFrame> =
(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<u8> = (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);