use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use sucds::bit_vectors::{
prelude::{Rank, Select},
Rank9Sel,
};
use sucds::mii_sequences::{EliasFano as SucdsEF, EliasFanoBuilder};
use vers_vecs::bit_vec::{fast_rs_vec::RsVec, BitVec};
use vers_vecs::EliasFanoVec as VersEF;
use sbits::BitVector as SbitsBV;
use sbits::EliasFano as SbitsEF;
const N_BITS: usize = 1_000_000;
const N_EF: usize = 100_000;
const EF_UNIVERSE: u64 = 4_000_001;
fn make_sbits_bv() -> SbitsBV {
let words = vec![0xAAAAAAAAAAAAAAAAu64; N_BITS / 64];
SbitsBV::new(&words, N_BITS)
}
fn make_sucds_bv() -> Rank9Sel {
let bits = (0..N_BITS).map(|i| i % 2 == 1);
Rank9Sel::from_bits(bits).select1_hints().select0_hints()
}
fn make_vers_bv() -> RsVec {
let words = vec![0xAAAAAAAAAAAAAAAAu64; N_BITS / 64];
let bv = BitVec::from_limbs(&words);
RsVec::from_bit_vec(bv)
}
fn make_sbits_ef() -> SbitsEF {
let values: Vec<u64> = (0..N_EF as u64).map(|i| i * 40).collect();
SbitsEF::new(&values, EF_UNIVERSE)
}
fn make_sucds_ef() -> SucdsEF {
let mut builder = EliasFanoBuilder::new(EF_UNIVERSE as usize, N_EF).unwrap();
for i in 0..N_EF {
builder.push(i * 40).unwrap();
}
builder.build().enable_rank()
}
fn make_vers_ef() -> VersEF {
let values: Vec<u64> = (0..N_EF as u64).map(|i| i * 40).collect();
VersEF::from_slice(&values)
}
fn bench_rank1(c: &mut Criterion) {
let sbits = make_sbits_bv();
let sucds = make_sucds_bv();
let vers = make_vers_bv();
let mut group = c.benchmark_group("rank1/1M_50pct");
let queries: Vec<usize> = (0..N_BITS).step_by(64).collect();
group.bench_function("sbits", |b| {
b.iter(|| {
for &pos in &queries {
black_box(sbits.rank1(pos));
}
})
});
group.bench_with_input(BenchmarkId::new("sucds", "Rank9Sel"), &(), |b, _| {
b.iter(|| {
for &pos in &queries {
black_box(sucds.rank1(pos));
}
})
});
group.bench_function("vers-vecs", |b| {
b.iter(|| {
for &pos in &queries {
black_box(vers.rank1(pos));
}
})
});
group.finish();
}
fn bench_select1(c: &mut Criterion) {
let sbits = make_sbits_bv();
let sucds = make_sucds_bv();
let vers = make_vers_bv();
let total_ones = N_BITS / 2; let mut group = c.benchmark_group("select1/1M_50pct");
let queries: Vec<usize> = (0..total_ones).step_by(512).collect();
group.bench_function("sbits", |b| {
b.iter(|| {
for &k in &queries {
black_box(sbits.select1(k));
}
})
});
group.bench_with_input(BenchmarkId::new("sucds", "Rank9Sel+hints"), &(), |b, _| {
b.iter(|| {
for &k in &queries {
black_box(sucds.select1(k));
}
})
});
group.bench_function("vers-vecs", |b| {
b.iter(|| {
for &k in &queries {
black_box(vers.select1(k));
}
})
});
group.finish();
}
fn bench_rank0(c: &mut Criterion) {
let sbits = make_sbits_bv();
let sucds = make_sucds_bv();
let vers = make_vers_bv();
let mut group = c.benchmark_group("rank0/1M_50pct");
let queries: Vec<usize> = (0..N_BITS).step_by(64).collect();
group.bench_function("sbits", |b| {
b.iter(|| {
for &pos in &queries {
black_box(sbits.rank0(pos));
}
})
});
group.bench_with_input(BenchmarkId::new("sucds", "Rank9Sel"), &(), |b, _| {
b.iter(|| {
for &pos in &queries {
black_box(sucds.rank0(pos));
}
})
});
group.bench_function("vers-vecs", |b| {
b.iter(|| {
for &pos in &queries {
black_box(vers.rank0(pos));
}
})
});
group.finish();
}
fn bench_select0(c: &mut Criterion) {
let sbits = make_sbits_bv();
let sucds = make_sucds_bv();
let vers = make_vers_bv();
let total_zeros = N_BITS / 2;
let mut group = c.benchmark_group("select0/1M_50pct");
let queries: Vec<usize> = (0..total_zeros).step_by(512).collect();
group.bench_function("sbits", |b| {
b.iter(|| {
for &k in &queries {
black_box(sbits.select0(k));
}
})
});
group.bench_with_input(BenchmarkId::new("sucds", "Rank9Sel+hints"), &(), |b, _| {
b.iter(|| {
for &k in &queries {
black_box(sucds.select0(k));
}
})
});
group.bench_function("vers-vecs", |b| {
b.iter(|| {
for &k in &queries {
black_box(vers.select0(k));
}
})
});
group.finish();
}
fn bench_ef_successor(c: &mut Criterion) {
let sbits_ef = make_sbits_ef();
let sucds_ef = make_sucds_ef();
let vers_ef = make_vers_ef();
let mut group = c.benchmark_group("ef_successor/100K");
let targets: Vec<u64> = (0..EF_UNIVERSE).step_by(4000).collect();
group.bench_function("sbits", |b| {
b.iter(|| {
for &t in &targets {
black_box(sbits_ef.successor(t));
}
})
});
group.bench_with_input(BenchmarkId::new("sucds", "EliasFano"), &(), |b, _| {
b.iter(|| {
for &t in &targets {
black_box(sucds_ef.successor(t as usize));
}
})
});
group.bench_function("vers-vecs", |b| {
b.iter(|| {
for &t in &targets {
black_box(vers_ef.successor(t));
}
})
});
group.finish();
}
fn bench_ef_contains(c: &mut Criterion) {
let sbits_ef = make_sbits_ef();
let sucds_ef = make_sucds_ef();
let vers_ef = make_vers_ef();
let mut group = c.benchmark_group("ef_contains/100K");
let targets: Vec<u64> = (0..EF_UNIVERSE).step_by(20).collect();
group.bench_function("sbits", |b| {
b.iter(|| {
for &t in &targets {
black_box(sbits_ef.contains(t));
}
})
});
group.bench_with_input(BenchmarkId::new("sucds", "EliasFano"), &(), |b, _| {
b.iter(|| {
for &t in &targets {
black_box(sucds_ef.binsearch(t as usize).is_some());
}
})
});
group.bench_function("vers-vecs", |b| {
b.iter(|| {
for &t in &targets {
black_box(vers_ef.successor(t) == Some(t));
}
})
});
group.finish();
}
fn bench_ef_rank(c: &mut Criterion) {
let sbits_ef = make_sbits_ef();
let sucds_ef = make_sucds_ef();
let vers_ef = make_vers_ef();
let mut group = c.benchmark_group("ef_rank/100K");
let targets: Vec<u64> = (0..EF_UNIVERSE).step_by(4000).collect();
group.bench_function("sbits", |b| {
b.iter(|| {
for &t in &targets {
black_box(sbits_ef.rank(t));
}
})
});
group.bench_with_input(BenchmarkId::new("sucds", "EliasFano"), &(), |b, _| {
b.iter(|| {
for &t in &targets {
black_box(sucds_ef.rank(t as usize));
}
})
});
group.bench_function("vers-vecs", |b| {
b.iter(|| {
for &t in &targets {
black_box(vers_ef.rank(t));
}
})
});
group.finish();
}
criterion_group!(
benches,
bench_rank1,
bench_select1,
bench_rank0,
bench_select0,
bench_ef_successor,
bench_ef_contains,
bench_ef_rank,
);
criterion_main!(benches);