Files
obikmer/src/obiskbuilder/benches/superkmer_stream.rs
T

59 lines
1.8 KiB
Rust
Raw Normal View History

//! Throughput of the streaming superkmer pipeline (`RollingStat`'s hot path:
//! minimizer selection + entropy tracking fused in a single pass).
//!
//! Reference point for the `obikentropy` extraction: the entropy bookkeeping
//! that used to live inline in `RollingStat` was pulled out into a composed
//! `EntropyTracker`. This benchmark is run before and after that change to
//! confirm no regression.
use criterion::{Criterion, Throughput, criterion_group, criterion_main};
use obikrope::Rope;
use obiskbuilder::SuperKmerIter;
const K: usize = 21;
const M: usize = 9;
const LEVEL_MAX: usize = 6;
const THETA: f64 = 0.7;
const SEQ_LEN: usize = 200_000;
/// Deterministic pseudo-random ACGT sequence — high enough complexity that
/// the entropy filter rarely rejects, so the bench stays on the steady-state
/// path rather than repeatedly resetting.
fn make_sequence(len: usize) -> Vec<u8> {
let mut state: u64 = 0x9E3779B97F4A7C15;
(0..len)
.map(|_| {
state ^= state << 13;
state ^= state >> 7;
state ^= state << 17;
b"ACGT"[(state % 4) as usize]
})
.collect()
}
fn make_rope(seq: &[u8]) -> Rope {
let mut rope = Rope::new(None);
rope.push(seq.to_vec());
rope
}
fn bench_build_superkmers(c: &mut Criterion) {
obikseq::set_k(K);
obikseq::set_m(M);
let seq = make_sequence(SEQ_LEN);
let rope = make_rope(&seq);
let mut group = c.benchmark_group("build_superkmers");
group.throughput(Throughput::Bytes(SEQ_LEN as u64));
group.bench_function("stream", |b| {
b.iter(|| {
SuperKmerIter::new(std::hint::black_box(&rope), K, LEVEL_MAX, THETA).count()
});
});
group.finish();
}
criterion_group!(benches, bench_build_superkmers);
criterion_main!(benches);