91 lines
3.8 KiB
Rust
91 lines
3.8 KiB
Rust
//! Gateway hotspot benches — pipelining/branchless, cache-lines, SoA, SIMD
|
|
//! Covers hpc/pipelining/branchless, hpc/cpu-cache/{cache-lines,alignment,aos-soa}, hpc/simd/*
|
|
use criterion::{criterion_group, criterion_main, Criterion, BenchmarkId};
|
|
use dashmap::DashMap;
|
|
|
|
fn bench_group_broadcast_filter(c: &mut Criterion) {
|
|
// Before: DashMap<String,DashSet<ConnId>> pointer chase per member
|
|
// After: Vec<ConnId> contiguous + tenant filter branchless
|
|
let mut group = c.benchmark_group("gateway_group_broadcast");
|
|
for &members in &[100, 500, 2000] {
|
|
// Simulate group_conn_index: Vec<ConnId> vs DashSet
|
|
let vec_members: Vec<u32> = (0..members).collect();
|
|
let map: DashMap<u32, String> = DashMap::new();
|
|
for &m in &vec_members { map.insert(m, if m % 2 == 0 { "US".into() } else { "BR".into() }); }
|
|
group.bench_with_input(BenchmarkId::new("branchy_filter", members), &members, |b, _| {
|
|
b.iter(|| {
|
|
let sender_tenant = "US";
|
|
let mut delivered = 0;
|
|
for &mid in &vec_members {
|
|
let t = map.get(&mid).unwrap().clone();
|
|
if t != sender_tenant { continue; } // branchy
|
|
delivered += 1;
|
|
}
|
|
std::hint::black_box(delivered)
|
|
});
|
|
});
|
|
group.bench_with_input(BenchmarkId::new("branchless_filter", members), &members, |b, _| {
|
|
b.iter(|| {
|
|
let sender_tenant = "US";
|
|
let mut delivered = 0;
|
|
for &mid in &vec_members {
|
|
let t = map.get(&mid).unwrap();
|
|
// branchless: cmov via mask
|
|
let eq = (t.as_str() == sender_tenant) as usize;
|
|
delivered += eq;
|
|
}
|
|
std::hint::black_box(delivered)
|
|
});
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_username_validation(c: &mut Criterion) {
|
|
// Scalar vs SIMD (memchr) — hpc/simd/auto-vectorization
|
|
let mut group = c.benchmark_group("username_validation");
|
|
let valid = "alice_123".repeat(10);
|
|
let invalid = "alice!@#".repeat(10);
|
|
for case in ["valid", "invalid"] {
|
|
let s = if case == "valid" { &valid } else { &invalid };
|
|
group.bench_with_input(BenchmarkId::new("scalar", case), &case, |b, _| {
|
|
b.iter(|| {
|
|
let ok = s.chars().all(|c| c.is_alphanumeric() || c=='_' || c=='-');
|
|
std::hint::black_box(ok)
|
|
});
|
|
});
|
|
group.bench_with_input(BenchmarkId::new("simd_table", case), &case, |b, _| {
|
|
// branchless table lookup (256 entry)
|
|
let table: [bool; 256] = {
|
|
let mut t = [false; 256];
|
|
for c in b'a'..=b'z' { t[c as usize]=true; }
|
|
for c in b'A'..=b'Z' { t[c as usize]=true; }
|
|
for c in b'0'..=b'9' { t[c as usize]=true; }
|
|
t[b'_' as usize]=true; t[b'-' as usize]=true;
|
|
t
|
|
};
|
|
b.iter(|| {
|
|
let ok = s.as_bytes().iter().all(|&b| table[b as usize]);
|
|
std::hint::black_box(ok)
|
|
});
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_rate_limiter_false_sharing(c: &mut Criterion) {
|
|
// Alignment: check false sharing cost
|
|
let mut group = c.benchmark_group("rate_limiter");
|
|
group.bench_function("atomic_unaligned", |b| {
|
|
let limiter = std::sync::atomic::AtomicU32::new(200);
|
|
b.iter(|| {
|
|
let v = limiter.load(std::sync::atomic::Ordering::Relaxed);
|
|
limiter.store(v.wrapping_sub(1), std::sync::atomic::Ordering::Relaxed);
|
|
std::hint::black_box(v)
|
|
});
|
|
});
|
|
group.finish();
|
|
}
|
|
|
|
criterion_group!(benches, bench_group_broadcast_filter, bench_username_validation, bench_rate_limiter_false_sharing);
|
|
criterion_main!(benches);
|