#![allow(missing_docs, unused_results)]
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use noyalib::simd::{SimdScanner, StructuralIter, find_any_of};
use std::hint::black_box;
const STRUCTURAL_NEEDLES: &[u8] = b":-[]{}\n#";
fn scalar_walk(haystack: &[u8], needles: &[u8]) -> usize {
let mut count = 0;
for &b in haystack {
if needles.contains(&b) {
count += 1;
}
}
count
}
fn memchr_walk(haystack: &[u8], needles: &[u8]) -> usize {
let mut count = 0;
let mut start = 0;
while start < haystack.len() {
match find_any_of(&haystack[start..], needles) {
Some(pos) => {
count += 1;
start += pos + 1;
}
None => break,
}
}
count
}
fn structural_iter_walk(haystack: &[u8], scanner: &SimdScanner) -> usize {
StructuralIter::new(scanner, haystack).count()
}
fn make_yaml_haystack(target_bytes: usize) -> Vec<u8> {
let template = b" - key_name: value-data-payload-here\n";
let mut out = Vec::with_capacity(target_bytes + template.len());
while out.len() < target_bytes {
out.extend_from_slice(template);
}
out
}
fn bench_structural(c: &mut Criterion) {
let mut group = c.benchmark_group("structural_discovery");
let scanner = SimdScanner::new(STRUCTURAL_NEEDLES);
for &(label, size) in &[
("4KiB", 4 * 1024usize),
("64KiB", 64 * 1024usize),
("1MiB", 1024 * 1024usize),
] {
let haystack = make_yaml_haystack(size);
group.throughput(Throughput::Bytes(haystack.len() as u64));
group.bench_with_input(BenchmarkId::new("scalar", label), &haystack, |b, h| {
b.iter(|| scalar_walk(black_box(h), STRUCTURAL_NEEDLES));
});
group.bench_with_input(
BenchmarkId::new("memchr_find_any_of", label),
&haystack,
|b, h| {
b.iter(|| memchr_walk(black_box(h), STRUCTURAL_NEEDLES));
},
);
group.bench_with_input(
BenchmarkId::new("structural_iter", label),
&haystack,
|b, h| {
b.iter(|| structural_iter_walk(black_box(h), &scanner));
},
);
}
group.finish();
}
criterion_group!(benches, bench_structural);
criterion_main!(benches);