708 lines
22 KiB
Rust
708 lines
22 KiB
Rust
//! Critical path latency benchmarks for ruQu Coherence Gate.
|
|
//!
|
|
//! Primary performance target: **sub-4μs gate decision latency (p99)**
|
|
//!
|
|
//! Latency Budget (Target: <4μs p99):
|
|
//! ```text
|
|
//! Syndrome Arrival → 0 ns
|
|
//! Ring buffer append → +50 ns
|
|
//! Graph update → +200 ns (amortized O(n^{o(1)}))
|
|
//! Worker Tick → +500 ns (local cut eval)
|
|
//! Report generation → +100 ns
|
|
//! TileZero Merge → +500 ns (parallel from 255 tiles)
|
|
//! Global cut → +300 ns
|
|
//! Three-filter eval → +100 ns
|
|
//! Token signing → +500 ns (Ed25519)
|
|
//! Receipt append → +100 ns
|
|
//! ─────────────────────────────────
|
|
//! Total → ~2,350 ns
|
|
//! ```
|
|
//!
|
|
//! Run with: `cargo bench -p ruqu --bench latency_bench`
|
|
|
|
use criterion::{
|
|
black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId,
|
|
Criterion, SamplingMode,
|
|
};
|
|
|
|
use ruqu::filters::{
|
|
EvidenceAccumulator as FilterEvidenceAccumulator, EvidenceFilter, FilterConfig, FilterPipeline,
|
|
ShiftFilter, StructuralFilter, SystemState,
|
|
};
|
|
use ruqu::tile::{
|
|
GateDecision, GateThresholds, LocalCutState, PatchGraph, SyndromeDelta, TileReport, TileZero,
|
|
WorkerTile,
|
|
};
|
|
|
|
// ============================================================================
|
|
// HELPER FUNCTIONS
|
|
// ============================================================================
|
|
|
|
/// Create a pre-populated worker tile for benchmarking
|
|
fn create_benchmark_worker_tile(tile_id: u8, num_vertices: u16, num_edges: u16) -> WorkerTile {
|
|
let mut tile = WorkerTile::new(tile_id);
|
|
|
|
// Add vertices and edges to the patch graph
|
|
for i in 0..num_vertices.min(255) {
|
|
tile.patch_graph.ensure_vertex(i);
|
|
}
|
|
|
|
// Add edges in a mesh pattern
|
|
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
|
|
}
|
|
|
|
/// Create a pre-populated filter pipeline for benchmarking
|
|
fn create_benchmark_filter_pipeline() -> FilterPipeline {
|
|
let config = FilterConfig::default();
|
|
let mut pipeline = FilterPipeline::new(config);
|
|
|
|
// Add graph structure
|
|
for i in 0..50u64 {
|
|
let _ = pipeline.structural_mut().insert_edge(i, i + 1, 1.0);
|
|
}
|
|
pipeline.structural_mut().build();
|
|
|
|
// Warm up shift filter with observations
|
|
for region in 0..10 {
|
|
for _ in 0..50 {
|
|
pipeline.shift_mut().update(region, 0.5);
|
|
}
|
|
}
|
|
|
|
// Warm up evidence filter
|
|
for _ in 0..20 {
|
|
pipeline.evidence_mut().update(1.5);
|
|
}
|
|
|
|
pipeline
|
|
}
|
|
|
|
/// Create benchmark tile reports
|
|
fn create_benchmark_tile_reports(count: usize) -> Vec<TileReport> {
|
|
(1..=count)
|
|
.map(|i| {
|
|
let mut report = TileReport::new(i as u8);
|
|
report.local_cut = 10.0 + (i as f64 * 0.1);
|
|
report.shift_score = 0.1 + (i as f64 * 0.01);
|
|
report.e_value = 100.0 + (i as f64);
|
|
report.num_vertices = 100;
|
|
report.num_edges = 200;
|
|
report.num_components = 1;
|
|
report
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
// ============================================================================
|
|
// GATE DECISION LATENCY (Critical Path)
|
|
// ============================================================================
|
|
|
|
/// Benchmark the full decision cycle - the critical <4μs path
|
|
fn bench_gate_decision(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("gate_decision");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Full decision cycle: worker tick + tilezero merge
|
|
group.bench_function("full_cycle", |b| {
|
|
let mut tile = create_benchmark_worker_tile(1, 64, 128);
|
|
let thresholds = GateThresholds::default();
|
|
let mut tilezero = TileZero::new(thresholds);
|
|
|
|
b.iter(|| {
|
|
// 1. Worker tick - process syndrome delta
|
|
let delta = SyndromeDelta::new(0, 1, 100);
|
|
let report = tile.tick(&delta);
|
|
|
|
// 2. TileZero merge reports (simulating all 255 tiles with the same report)
|
|
let reports = vec![report; 10]; // Reduced for single-threaded benchmark
|
|
let decision = tilezero.merge_reports(reports);
|
|
|
|
black_box(decision)
|
|
});
|
|
});
|
|
|
|
// Worker tick only
|
|
group.bench_function("worker_tick_only", |b| {
|
|
let mut tile = create_benchmark_worker_tile(1, 64, 128);
|
|
let delta = SyndromeDelta::new(0, 1, 100);
|
|
|
|
b.iter(|| {
|
|
let report = tile.tick(black_box(&delta));
|
|
black_box(report)
|
|
});
|
|
});
|
|
|
|
// TileZero merge only
|
|
group.bench_function("tilezero_merge_only", |b| {
|
|
let thresholds = GateThresholds::default();
|
|
let mut tilezero = TileZero::new(thresholds);
|
|
let reports = create_benchmark_tile_reports(255);
|
|
|
|
b.iter(|| {
|
|
let decision = tilezero.merge_reports(black_box(reports.clone()));
|
|
black_box(decision)
|
|
});
|
|
});
|
|
|
|
// TileZero merge with varying tile counts
|
|
for tile_count in [10, 50, 100, 255].iter() {
|
|
group.bench_with_input(
|
|
BenchmarkId::new("tilezero_merge_tiles", tile_count),
|
|
tile_count,
|
|
|b, &count| {
|
|
let thresholds = GateThresholds::default();
|
|
let mut tilezero = TileZero::new(thresholds);
|
|
let reports = create_benchmark_tile_reports(count);
|
|
|
|
b.iter(|| {
|
|
let decision = tilezero.merge_reports(black_box(reports.clone()));
|
|
black_box(decision)
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// INDIVIDUAL FILTER EVALUATION LATENCY
|
|
// ============================================================================
|
|
|
|
/// Benchmark structural (min-cut) filter evaluation
|
|
fn bench_structural_filter(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("structural_filter");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Basic evaluation with small graph
|
|
group.bench_function("evaluate_small", |b| {
|
|
let mut filter = StructuralFilter::new(2.0);
|
|
for i in 0..20u64 {
|
|
let _ = filter.insert_edge(i, i + 1, 1.0);
|
|
}
|
|
filter.build();
|
|
let state = SystemState::new(20);
|
|
|
|
b.iter(|| {
|
|
let result = filter.evaluate(black_box(&state));
|
|
black_box(result)
|
|
});
|
|
});
|
|
|
|
// Evaluation with medium graph
|
|
group.bench_function("evaluate_medium", |b| {
|
|
let mut filter = StructuralFilter::new(2.0);
|
|
for i in 0..100u64 {
|
|
let _ = filter.insert_edge(i, (i + 1) % 100, 1.0);
|
|
let _ = filter.insert_edge(i, (i + 50) % 100, 0.5);
|
|
}
|
|
filter.build();
|
|
let state = SystemState::new(100);
|
|
|
|
b.iter(|| {
|
|
let result = filter.evaluate(black_box(&state));
|
|
black_box(result)
|
|
});
|
|
});
|
|
|
|
// Edge insertion (hot path during updates)
|
|
group.bench_function("insert_edge", |b| {
|
|
b.iter_batched(
|
|
|| (StructuralFilter::new(2.0), 0u64),
|
|
|(mut filter, mut edge_id)| {
|
|
for _ in 0..100 {
|
|
let u = edge_id % 256;
|
|
let v = (edge_id + 1) % 256;
|
|
let _ = filter.insert_edge(u, v, 1.0);
|
|
edge_id += 2;
|
|
}
|
|
black_box(edge_id)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
);
|
|
});
|
|
|
|
// Edge deletion
|
|
group.bench_function("delete_edge", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let mut filter = StructuralFilter::new(2.0);
|
|
for i in 0..100u64 {
|
|
let _ = filter.insert_edge(i, i + 1, 1.0);
|
|
}
|
|
filter
|
|
},
|
|
|mut filter| {
|
|
let result = filter.delete_edge(50, 51);
|
|
black_box(result)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
);
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark shift (drift detection) filter evaluation
|
|
fn bench_shift_filter(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("shift_filter");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Evaluate with warm filter
|
|
group.bench_function("evaluate_warm", |b| {
|
|
let mut filter = ShiftFilter::new(0.5, 100);
|
|
// Warm up with observations
|
|
for region in 0..64 {
|
|
for _ in 0..100 {
|
|
filter.update(region, 0.5 + (region as f64 * 0.001));
|
|
}
|
|
}
|
|
let state = SystemState::new(100);
|
|
|
|
b.iter(|| {
|
|
let result = filter.evaluate(black_box(&state));
|
|
black_box(result)
|
|
});
|
|
});
|
|
|
|
// Evaluate with cold filter
|
|
group.bench_function("evaluate_cold", |b| {
|
|
let filter = ShiftFilter::new(0.5, 100);
|
|
let state = SystemState::new(100);
|
|
|
|
b.iter(|| {
|
|
let result = filter.evaluate(black_box(&state));
|
|
black_box(result)
|
|
});
|
|
});
|
|
|
|
// Single update operation
|
|
group.bench_function("update_single", |b| {
|
|
let mut filter = ShiftFilter::new(0.5, 100);
|
|
let mut i = 0usize;
|
|
|
|
b.iter(|| {
|
|
filter.update(black_box(i % 64), black_box(0.5));
|
|
i += 1;
|
|
});
|
|
});
|
|
|
|
// Batch update (64 regions)
|
|
group.bench_function("update_batch_64", |b| {
|
|
let mut filter = ShiftFilter::new(0.5, 100);
|
|
|
|
b.iter(|| {
|
|
for region in 0..64 {
|
|
filter.update(black_box(region), black_box(0.5));
|
|
}
|
|
});
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark evidence (e-value) filter evaluation
|
|
fn bench_evidence_filter(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("evidence_filter");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Evaluate with accumulated evidence
|
|
group.bench_function("evaluate_accumulated", |b| {
|
|
let mut filter = EvidenceFilter::new(20.0, 0.05);
|
|
for _ in 0..100 {
|
|
filter.update(1.5);
|
|
}
|
|
let state = SystemState::new(100);
|
|
|
|
b.iter(|| {
|
|
let result = filter.evaluate(black_box(&state));
|
|
black_box(result)
|
|
});
|
|
});
|
|
|
|
// Single evidence update
|
|
group.bench_function("update_single", |b| {
|
|
let mut filter = EvidenceFilter::new(20.0, 0.05);
|
|
|
|
b.iter(|| {
|
|
filter.update(black_box(1.5));
|
|
});
|
|
});
|
|
|
|
// Evidence accumulator operations
|
|
group.bench_function("accumulator_observe", |b| {
|
|
let mut accumulator = FilterEvidenceAccumulator::new();
|
|
|
|
b.iter(|| {
|
|
accumulator.update(black_box(1.5));
|
|
});
|
|
});
|
|
|
|
group.bench_function("accumulator_e_value", |b| {
|
|
let mut accumulator = FilterEvidenceAccumulator::new();
|
|
for _ in 0..100 {
|
|
accumulator.update(1.5);
|
|
}
|
|
|
|
b.iter(|| {
|
|
let e = accumulator.e_value();
|
|
black_box(e)
|
|
});
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// TILE PROCESSING LATENCY
|
|
// ============================================================================
|
|
|
|
/// Benchmark worker tile tick processing
|
|
fn bench_worker_tile_tick(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("worker_tile_tick");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Tick with syndrome delta
|
|
group.bench_function("tick_syndrome", |b| {
|
|
let mut tile = create_benchmark_worker_tile(1, 64, 128);
|
|
let delta = SyndromeDelta::new(0, 1, 100);
|
|
|
|
b.iter(|| {
|
|
let report = tile.tick(black_box(&delta));
|
|
black_box(report)
|
|
});
|
|
});
|
|
|
|
// Tick with edge addition
|
|
group.bench_function("tick_edge_add", |b| {
|
|
let mut tile = create_benchmark_worker_tile(1, 64, 128);
|
|
let delta = SyndromeDelta::edge_add(10, 20, 1000);
|
|
|
|
b.iter(|| {
|
|
let report = tile.tick(black_box(&delta));
|
|
black_box(report)
|
|
});
|
|
});
|
|
|
|
// Tick with edge removal
|
|
group.bench_function("tick_edge_remove", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let mut tile = create_benchmark_worker_tile(1, 64, 128);
|
|
// Add edge before removing
|
|
let _ = tile.patch_graph.add_edge(5, 6, 1000);
|
|
(tile, SyndromeDelta::edge_remove(5, 6))
|
|
},
|
|
|(mut tile, delta)| {
|
|
let report = tile.tick(&delta);
|
|
black_box(report)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
);
|
|
});
|
|
|
|
// Varying graph sizes
|
|
for (vertices, edges) in [(32, 64), (64, 128), (128, 256), (200, 400)].iter() {
|
|
group.bench_with_input(
|
|
BenchmarkId::new("tick_graph_size", format!("v{}e{}", vertices, edges)),
|
|
&(*vertices, *edges),
|
|
|b, &(v, e)| {
|
|
let mut tile = create_benchmark_worker_tile(1, v, e);
|
|
let delta = SyndromeDelta::new(0, 1, 100);
|
|
|
|
b.iter(|| {
|
|
let report = tile.tick(black_box(&delta));
|
|
black_box(report)
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
group.finish();
|
|
}
|
|
|
|
/// Benchmark TileZero merge operations
|
|
fn bench_tilezero_merge(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("tilezero_merge");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Merge leading to PERMIT
|
|
group.bench_function("merge_permit", |b| {
|
|
let thresholds = GateThresholds::default();
|
|
let mut tilezero = TileZero::new(thresholds);
|
|
|
|
let reports: Vec<TileReport> = (1..=100)
|
|
.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(|| {
|
|
let decision = tilezero.merge_reports(black_box(reports.clone()));
|
|
debug_assert_eq!(decision, GateDecision::Permit);
|
|
black_box(decision)
|
|
});
|
|
});
|
|
|
|
// Merge leading to DENY (structural)
|
|
group.bench_function("merge_deny_structural", |b| {
|
|
let thresholds = GateThresholds::default();
|
|
let mut tilezero = TileZero::new(thresholds);
|
|
|
|
let reports: Vec<TileReport> = (1..=100)
|
|
.map(|i| {
|
|
let mut report = TileReport::new(i as u8);
|
|
report.local_cut = 1.0; // Below threshold
|
|
report.shift_score = 0.1;
|
|
report.e_value = 200.0;
|
|
report
|
|
})
|
|
.collect();
|
|
|
|
b.iter(|| {
|
|
let decision = tilezero.merge_reports(black_box(reports.clone()));
|
|
debug_assert_eq!(decision, GateDecision::Deny);
|
|
black_box(decision)
|
|
});
|
|
});
|
|
|
|
// Merge leading to DEFER (shift)
|
|
group.bench_function("merge_defer_shift", |b| {
|
|
let thresholds = GateThresholds::default();
|
|
let mut tilezero = TileZero::new(thresholds);
|
|
|
|
let reports: Vec<TileReport> = (1..=100)
|
|
.map(|i| {
|
|
let mut report = TileReport::new(i as u8);
|
|
report.local_cut = 10.0;
|
|
report.shift_score = 0.8; // Above threshold
|
|
report.e_value = 200.0;
|
|
report
|
|
})
|
|
.collect();
|
|
|
|
b.iter(|| {
|
|
let decision = tilezero.merge_reports(black_box(reports.clone()));
|
|
debug_assert_eq!(decision, GateDecision::Defer);
|
|
black_box(decision)
|
|
});
|
|
});
|
|
|
|
// Permit token issuance
|
|
group.bench_function("issue_permit", |b| {
|
|
let thresholds = GateThresholds::default();
|
|
let tilezero = TileZero::new(thresholds);
|
|
let decision = GateDecision::Permit;
|
|
|
|
b.iter(|| {
|
|
let token = tilezero.issue_permit(black_box(&decision));
|
|
black_box(token)
|
|
});
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// PATCH GRAPH LATENCY
|
|
// ============================================================================
|
|
|
|
/// Benchmark patch graph operations (critical for structural filter)
|
|
fn bench_patch_graph_operations(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("patch_graph");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Edge addition
|
|
group.bench_function("add_edge", |b| {
|
|
b.iter_batched(
|
|
PatchGraph::new,
|
|
|mut graph| {
|
|
for edge_count in 0..100u16 {
|
|
let v1 = (edge_count * 2) % 256;
|
|
let v2 = (edge_count * 2 + 1) % 256;
|
|
let _ = graph.add_edge(v1, v2, 1000);
|
|
}
|
|
black_box(graph.num_edges)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
);
|
|
});
|
|
|
|
// Edge removal
|
|
group.bench_function("remove_edge", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let mut graph = PatchGraph::new();
|
|
for i in 0..100u16 {
|
|
let _ = graph.add_edge(i, i + 1, 1000);
|
|
}
|
|
graph
|
|
},
|
|
|mut graph| {
|
|
let removed = graph.remove_edge(50, 51);
|
|
black_box(removed)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
);
|
|
});
|
|
|
|
// Local cut estimation
|
|
group.bench_function("estimate_local_cut", |b| {
|
|
let mut graph = PatchGraph::new();
|
|
for i in 0..100u16 {
|
|
let _ = graph.add_edge(i, (i + 1) % 100, 1000);
|
|
let _ = graph.add_edge(i, (i + 50) % 100, 500);
|
|
}
|
|
graph.recompute_components();
|
|
|
|
b.iter(|| {
|
|
let cut = graph.estimate_local_cut();
|
|
black_box(cut)
|
|
});
|
|
});
|
|
|
|
// Component recomputation
|
|
group.bench_function("recompute_components", |b| {
|
|
let mut graph = PatchGraph::new();
|
|
for i in 0..100u16 {
|
|
let _ = graph.add_edge(i, (i + 1) % 100, 1000);
|
|
}
|
|
|
|
b.iter(|| {
|
|
graph.status |= PatchGraph::STATUS_DIRTY;
|
|
let count = graph.recompute_components();
|
|
black_box(count)
|
|
});
|
|
});
|
|
|
|
// Boundary candidate identification
|
|
group.bench_function("identify_boundary_candidates", |b| {
|
|
let mut graph = PatchGraph::new();
|
|
for i in 0..100u16 {
|
|
let _ = graph.add_edge(i, (i + 1) % 100, 1000);
|
|
}
|
|
graph.recompute_components();
|
|
let mut candidates = [0u16; 64];
|
|
|
|
b.iter(|| {
|
|
let count = graph.identify_boundary_candidates(&mut candidates);
|
|
black_box(count)
|
|
});
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// LOCAL CUT STATE LATENCY
|
|
// ============================================================================
|
|
|
|
/// Benchmark local cut state operations
|
|
fn bench_local_cut_state(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("local_cut_state");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Update from graph
|
|
group.bench_function("update_from_graph", |b| {
|
|
let mut graph = PatchGraph::new();
|
|
for i in 0..100u16 {
|
|
let _ = graph.add_edge(i, (i + 1) % 100, 1000);
|
|
}
|
|
graph.recompute_components();
|
|
|
|
let mut cut_state = LocalCutState::new();
|
|
|
|
b.iter(|| {
|
|
cut_state.update_from_graph(&graph);
|
|
black_box(cut_state.cut_value)
|
|
});
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// FILTER PIPELINE LATENCY
|
|
// ============================================================================
|
|
|
|
/// Benchmark full filter pipeline evaluation
|
|
fn bench_filter_pipeline(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("filter_pipeline");
|
|
group.sampling_mode(SamplingMode::Flat);
|
|
group.sample_size(1000);
|
|
|
|
// Full evaluation
|
|
group.bench_function("evaluate_full", |b| {
|
|
let pipeline = create_benchmark_filter_pipeline();
|
|
let state = SystemState::new(100);
|
|
|
|
b.iter(|| {
|
|
let result = pipeline.evaluate(black_box(&state));
|
|
black_box(result)
|
|
});
|
|
});
|
|
|
|
// Cold start evaluation
|
|
group.bench_function("evaluate_cold", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let config = FilterConfig::default();
|
|
let pipeline = FilterPipeline::new(config);
|
|
let state = SystemState::new(100);
|
|
(pipeline, state)
|
|
},
|
|
|(pipeline, state)| {
|
|
let result = pipeline.evaluate(&state);
|
|
black_box(result)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
);
|
|
});
|
|
|
|
group.finish();
|
|
}
|
|
|
|
// ============================================================================
|
|
// CRITERION GROUPS
|
|
// ============================================================================
|
|
|
|
criterion_group!(
|
|
latency_benches,
|
|
bench_gate_decision,
|
|
bench_structural_filter,
|
|
bench_shift_filter,
|
|
bench_evidence_filter,
|
|
bench_worker_tile_tick,
|
|
bench_tilezero_merge,
|
|
bench_patch_graph_operations,
|
|
bench_local_cut_state,
|
|
bench_filter_pipeline,
|
|
);
|
|
|
|
criterion_main!(latency_benches);
|