Files
wifi-densepose/vendor/ruvector/crates/ruQu/benches/throughput_bench.rs

704 lines
22 KiB
Rust

//! Throughput benchmarks for ruQu Coherence Gate.
//!
//! Performance Targets:
//! - Syndrome ingestion rate: **1M rounds/sec**
//! - Gate decisions per second: **250K decisions/sec**
//! - Permit token generation rate: **100K tokens/sec**
//!
//! Run with: `cargo bench -p ruqu --bench throughput_bench`
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use ruqu::filters::{FilterConfig, FilterPipeline, SystemState};
use ruqu::syndrome::{DetectorBitmap, SyndromeBuffer, SyndromeDelta, SyndromeRound};
use ruqu::tile::{
GateDecision, GateThresholds, PatchGraph, PermitToken, ReceiptLog,
SyndromeDelta as TileSyndromeDelta, TileReport, TileZero, WorkerTile,
};
// ============================================================================
// HELPER FUNCTIONS
// ============================================================================
/// Create a syndrome round with specified firing pattern
fn create_syndrome_round(round_id: u64, detector_count: usize, firing_rate: f64) -> SyndromeRound {
let mut detectors = DetectorBitmap::new(detector_count);
let num_fired = ((detector_count as f64) * firing_rate) as usize;
for i in 0..num_fired {
detectors.set(i * (detector_count / num_fired.max(1)), true);
}
SyndromeRound::new(round_id, round_id, round_id * 1000, detectors, 0)
}
/// Create a worker tile with pre-populated graph
fn create_worker_tile(tile_id: u8, num_vertices: u16, num_edges: u16) -> WorkerTile {
let mut tile = WorkerTile::new(tile_id);
for i in 0..num_vertices.min(255) {
tile.patch_graph.ensure_vertex(i);
}
let mut edges_added = 0u16;
'outer: for i in 0..num_vertices.saturating_sub(1) {
for j in (i + 1)..num_vertices.min(i + 4) {
if edges_added >= num_edges {
break 'outer;
}
if tile.patch_graph.add_edge(i, j, 1000).is_some() {
edges_added += 1;
}
}
}
tile.patch_graph.recompute_components();
tile
}
// ============================================================================
// SYNDROME INGESTION THROUGHPUT
// ============================================================================
/// Benchmark syndrome ingestion rate (target: 1M rounds/sec)
fn bench_syndrome_ingestion(c: &mut Criterion) {
let mut group = c.benchmark_group("syndrome_ingestion");
// Single round ingestion
group.throughput(Throughput::Elements(1));
group.bench_function("single_round", |b| {
let mut buffer = SyndromeBuffer::new(4096);
let mut round_id = 0u64;
b.iter(|| {
let round = create_syndrome_round(round_id, 64, 0.1);
buffer.push(round);
round_id += 1;
black_box(&buffer);
});
});
// Batch ingestion (1000 rounds)
group.throughput(Throughput::Elements(1000));
group.bench_function("batch_1000_rounds", |b| {
let mut buffer = SyndromeBuffer::new(4096);
let mut round_id = 0u64;
b.iter(|| {
for _ in 0..1000 {
let round = create_syndrome_round(round_id, 64, 0.1);
buffer.push(round);
round_id += 1;
}
black_box(&buffer);
});
});
// Large batch ingestion (10000 rounds)
group.throughput(Throughput::Elements(10_000));
group.bench_function("batch_10000_rounds", |b| {
let mut buffer = SyndromeBuffer::new(16384);
let mut round_id = 0u64;
b.iter(|| {
for _ in 0..10_000 {
let round = create_syndrome_round(round_id, 64, 0.1);
buffer.push(round);
round_id += 1;
}
black_box(&buffer);
});
});
// Varying detector counts
for detector_count in [64, 256, 512, 1024].iter() {
group.throughput(Throughput::Elements(1000));
group.bench_with_input(
BenchmarkId::new("batch_1000_detectors", detector_count),
detector_count,
|b, &count| {
let mut buffer = SyndromeBuffer::new(4096);
let mut round_id = 0u64;
b.iter(|| {
for _ in 0..1000 {
let round = create_syndrome_round(round_id, count, 0.1);
buffer.push(round);
round_id += 1;
}
black_box(&buffer);
});
},
);
}
// Varying firing rates
for firing_rate in [0.01, 0.05, 0.1, 0.25].iter() {
group.throughput(Throughput::Elements(1000));
group.bench_with_input(
BenchmarkId::new(
"batch_1000_firing_rate",
format!("{:.0}pct", firing_rate * 100.0),
),
firing_rate,
|b, &rate| {
let mut buffer = SyndromeBuffer::new(4096);
let mut round_id = 0u64;
b.iter(|| {
for _ in 0..1000 {
let round = create_syndrome_round(round_id, 256, rate);
buffer.push(round);
round_id += 1;
}
black_box(&buffer);
});
},
);
}
group.finish();
}
// ============================================================================
// GATE DECISION THROUGHPUT
// ============================================================================
/// Benchmark gate decisions per second
fn bench_gate_decision_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("gate_decisions");
// Single decision
group.throughput(Throughput::Elements(1));
group.bench_function("single_decision", |b| {
let mut tile = create_worker_tile(1, 64, 128);
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
b.iter(|| {
let delta = TileSyndromeDelta::new(0, 1, 100);
let report = tile.tick(&delta);
let reports = vec![report; 10];
let decision = tilezero.merge_reports(reports);
black_box(decision)
});
});
// Batch decisions (100)
group.throughput(Throughput::Elements(100));
group.bench_function("batch_100_decisions", |b| {
let mut tile = create_worker_tile(1, 64, 128);
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
b.iter(|| {
for i in 0..100 {
let delta = TileSyndromeDelta::new(0, 1, i as u16);
let report = tile.tick(&delta);
let reports = vec![report; 10];
let decision = tilezero.merge_reports(reports);
black_box(decision);
}
});
});
// Batch decisions (1000)
group.throughput(Throughput::Elements(1000));
group.bench_function("batch_1000_decisions", |b| {
let mut tile = create_worker_tile(1, 64, 128);
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
b.iter(|| {
for i in 0..1000 {
let delta = TileSyndromeDelta::new(0, 1, (i % 256) as u16);
let report = tile.tick(&delta);
let reports = vec![report; 10];
let decision = tilezero.merge_reports(reports);
black_box(decision);
}
});
});
// Decisions with varying tile counts
for tile_count in [10, 50, 100, 255].iter() {
group.throughput(Throughput::Elements(100));
group.bench_with_input(
BenchmarkId::new("batch_100_tile_count", tile_count),
tile_count,
|b, &count| {
let mut tile = create_worker_tile(1, 64, 128);
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
let base_reports: Vec<TileReport> = (1..=count)
.map(|i| {
let mut report = TileReport::new(i as u8);
report.local_cut = 10.0;
report.shift_score = 0.1;
report.e_value = 200.0;
report
})
.collect();
b.iter(|| {
for _ in 0..100 {
let delta = TileSyndromeDelta::new(0, 1, 100);
let _ = tile.tick(&delta);
let decision = tilezero.merge_reports(base_reports.clone());
black_box(decision);
}
});
},
);
}
group.finish();
}
// ============================================================================
// PERMIT TOKEN GENERATION THROUGHPUT
// ============================================================================
/// Benchmark permit token generation rate
fn bench_permit_token_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("permit_tokens");
// Single token
group.throughput(Throughput::Elements(1));
group.bench_function("single_token", |b| {
let thresholds = GateThresholds::default();
let tilezero = TileZero::new(thresholds);
let decision = GateDecision::Permit;
b.iter(|| {
let token = tilezero.issue_permit(&decision);
black_box(token)
});
});
// Batch tokens (1000)
group.throughput(Throughput::Elements(1000));
group.bench_function("batch_1000_tokens", |b| {
let thresholds = GateThresholds::default();
let tilezero = TileZero::new(thresholds);
let decision = GateDecision::Permit;
b.iter(|| {
for _ in 0..1000 {
let token = tilezero.issue_permit(&decision);
black_box(&token);
}
});
});
// Token validation throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("validate_1000_tokens", |b| {
let thresholds = GateThresholds::default();
let tilezero = TileZero::new(thresholds);
let token = tilezero.issue_permit(&GateDecision::Permit);
let now_ns = token.timestamp + 1000;
b.iter(|| {
for _ in 0..1000 {
let valid = token.is_valid(now_ns);
black_box(valid);
}
});
});
group.finish();
}
// ============================================================================
// RECEIPT LOG THROUGHPUT
// ============================================================================
/// Benchmark receipt log operations
fn bench_receipt_log_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("receipt_log");
// Append throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("append_1000", |b| {
let mut log = ReceiptLog::new();
let witness_hash = [0u8; 32];
b.iter(|| {
for i in 0..1000 {
log.append(GateDecision::Permit, i, i * 1000, witness_hash);
}
black_box(&log);
});
});
// Lookup throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("lookup_1000", |b| {
let mut log = ReceiptLog::new();
let witness_hash = [0u8; 32];
for i in 0..10000 {
log.append(GateDecision::Permit, i, i * 1000, witness_hash);
}
b.iter(|| {
for i in 0..1000 {
let entry = log.get(i * 10);
black_box(entry);
}
});
});
group.finish();
}
// ============================================================================
// WORKER TILE THROUGHPUT
// ============================================================================
/// Benchmark worker tile tick throughput
fn bench_worker_tile_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("worker_tile");
// Single tick
group.throughput(Throughput::Elements(1));
group.bench_function("single_tick", |b| {
let mut tile = create_worker_tile(1, 64, 128);
b.iter(|| {
let delta = TileSyndromeDelta::new(0, 1, 100);
let report = tile.tick(&delta);
black_box(report)
});
});
// Batch ticks (1000)
group.throughput(Throughput::Elements(1000));
group.bench_function("batch_1000_ticks", |b| {
let mut tile = create_worker_tile(1, 64, 128);
b.iter(|| {
for i in 0..1000 {
let delta = TileSyndromeDelta::new(0, 1, (i % 256) as u16);
let report = tile.tick(&delta);
black_box(&report);
}
});
});
// Sustained throughput (10000 ticks)
group.throughput(Throughput::Elements(10_000));
group.bench_function("sustained_10000_ticks", |b| {
let mut tile = create_worker_tile(1, 64, 128);
b.iter(|| {
for i in 0..10_000 {
let delta = TileSyndromeDelta::new(0, 1, (i % 256) as u16);
let report = tile.tick(&delta);
black_box(&report);
}
});
});
// Varying graph sizes
for (vertices, edges) in [(32, 64), (64, 128), (128, 256), (200, 400)].iter() {
group.throughput(Throughput::Elements(1000));
group.bench_with_input(
BenchmarkId::new("batch_1000_graph", format!("v{}e{}", vertices, edges)),
&(*vertices, *edges),
|b, &(v, e)| {
let mut tile = create_worker_tile(1, v, e);
b.iter(|| {
for i in 0..1000 {
let delta = TileSyndromeDelta::new(0, 1, (i % 256) as u16);
let report = tile.tick(&delta);
black_box(&report);
}
});
},
);
}
group.finish();
}
// ============================================================================
// FILTER PIPELINE THROUGHPUT
// ============================================================================
/// Benchmark filter pipeline throughput
fn bench_filter_pipeline_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("filter_pipeline");
// Create a pre-warmed pipeline
let create_pipeline = || {
let config = FilterConfig::default();
let mut pipeline = FilterPipeline::new(config);
for i in 0..50u64 {
let _ = pipeline.structural_mut().insert_edge(i, i + 1, 1.0);
}
pipeline.structural_mut().build();
for region in 0..10 {
for _ in 0..50 {
pipeline.shift_mut().update(region, 0.5);
}
}
for _ in 0..20 {
pipeline.evidence_mut().update(1.5);
}
pipeline
};
// Single evaluation
group.throughput(Throughput::Elements(1));
group.bench_function("single_evaluation", |b| {
let pipeline = create_pipeline();
let state = SystemState::new(100);
b.iter(|| {
let result = pipeline.evaluate(&state);
black_box(result)
});
});
// Batch evaluations (1000)
group.throughput(Throughput::Elements(1000));
group.bench_function("batch_1000_evaluations", |b| {
let pipeline = create_pipeline();
let state = SystemState::new(100);
b.iter(|| {
for _ in 0..1000 {
let result = pipeline.evaluate(&state);
black_box(&result);
}
});
});
group.finish();
}
// ============================================================================
// SYNDROME DELTA COMPUTATION THROUGHPUT
// ============================================================================
/// Benchmark syndrome delta computation throughput
fn bench_syndrome_delta_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("syndrome_delta");
// Create test rounds
let create_rounds = |count: usize| -> Vec<SyndromeRound> {
(0..count)
.map(|i| create_syndrome_round(i as u64, 256, 0.1))
.collect()
};
// Single delta computation
group.throughput(Throughput::Elements(1));
group.bench_function("single_delta", |b| {
let round1 = create_syndrome_round(0, 256, 0.1);
let round2 = create_syndrome_round(1, 256, 0.1);
b.iter(|| {
let delta = SyndromeDelta::compute(&round1, &round2);
black_box(delta)
});
});
// Batch delta computation (1000)
group.throughput(Throughput::Elements(999));
group.bench_function("batch_1000_deltas", |b| {
let rounds = create_rounds(1000);
b.iter(|| {
for i in 0..999 {
let delta = SyndromeDelta::compute(&rounds[i], &rounds[i + 1]);
black_box(&delta);
}
});
});
// Varying detector counts
for detector_count in [64, 256, 512, 1024].iter() {
group.throughput(Throughput::Elements(999));
group.bench_with_input(
BenchmarkId::new("batch_1000_detectors", detector_count),
detector_count,
|b, &count| {
let rounds: Vec<SyndromeRound> = (0..1000)
.map(|i| create_syndrome_round(i as u64, count, 0.1))
.collect();
b.iter(|| {
for i in 0..999 {
let delta = SyndromeDelta::compute(&rounds[i], &rounds[i + 1]);
black_box(&delta);
}
});
},
);
}
group.finish();
}
// ============================================================================
// PATCH GRAPH THROUGHPUT
// ============================================================================
/// Benchmark patch graph operation throughput
fn bench_patch_graph_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("patch_graph_throughput");
// Edge insertion throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("insert_1000_edges", |b| {
b.iter_batched(
PatchGraph::new,
|mut graph| {
for i in 0..1000u16 {
let v1 = i % 256;
let v2 = (i + 1) % 256;
if v1 != v2 {
let _ = graph.add_edge(v1, v2, 1000);
}
}
black_box(graph.num_edges)
},
criterion::BatchSize::SmallInput,
);
});
// Delta application throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("apply_1000_deltas", |b| {
b.iter_batched(
|| {
let mut graph = PatchGraph::new();
for i in 0..100u16 {
let _ = graph.add_edge(i, (i + 1) % 100, 1000);
}
graph
},
|mut graph| {
for i in 0..1000u16 {
let delta = TileSyndromeDelta::new(i % 100, (i + 1) % 100, 100);
graph.apply_delta(&delta);
}
black_box(graph.num_edges)
},
criterion::BatchSize::SmallInput,
);
});
// Component recomputation throughput
group.throughput(Throughput::Elements(100));
group.bench_function("recompute_100_times", |b| {
b.iter_batched(
|| {
let mut graph = PatchGraph::new();
for i in 0..200u16 {
let _ = graph.add_edge(i, (i + 1) % 200, 1000);
}
graph
},
|mut graph| {
let mut count = 0u16;
for _ in 0..100 {
graph.status |= PatchGraph::STATUS_DIRTY;
count = graph.recompute_components();
}
black_box(count)
},
criterion::BatchSize::SmallInput,
);
});
group.finish();
}
// ============================================================================
// DETECTOR BITMAP THROUGHPUT
// ============================================================================
/// Benchmark detector bitmap throughput
fn bench_bitmap_throughput(c: &mut Criterion) {
let mut group = c.benchmark_group("bitmap_throughput");
// XOR throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("xor_1000", |b| {
let mut a = DetectorBitmap::new(1024);
let mut bb = DetectorBitmap::new(1024);
for i in (0..512).step_by(2) {
a.set(i, true);
}
for i in (256..768).step_by(2) {
bb.set(i, true);
}
b.iter(|| {
for _ in 0..1000 {
let result = a.xor(&bb);
black_box(&result);
}
});
});
// Popcount throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("popcount_1000", |b| {
let mut bitmap = DetectorBitmap::new(1024);
for i in (0..512).step_by(2) {
bitmap.set(i, true);
}
b.iter(|| {
let mut total = 0usize;
for _ in 0..1000 {
total += bitmap.popcount();
}
black_box(total)
});
});
// Iterator throughput
group.throughput(Throughput::Elements(1000));
group.bench_function("iter_fired_1000", |b| {
let mut bitmap = DetectorBitmap::new(1024);
for i in 0..100 {
bitmap.set(i * 10, true);
}
b.iter(|| {
let mut total = 0usize;
for _ in 0..1000 {
total += bitmap.iter_fired().count();
}
black_box(total)
});
});
group.finish();
}
// ============================================================================
// CRITERION GROUPS
// ============================================================================
criterion_group!(
throughput_benches,
bench_syndrome_ingestion,
bench_gate_decision_throughput,
bench_permit_token_throughput,
bench_receipt_log_throughput,
bench_worker_tile_throughput,
bench_filter_pipeline_throughput,
bench_syndrome_delta_throughput,
bench_patch_graph_throughput,
bench_bitmap_throughput,
);
criterion_main!(throughput_benches);