use core::hint::black_box;
use std::path::Path;
use criterion::{criterion_group, criterion_main, Criterion};
use array_range_query::SegTreeSum;
const SIZE: usize = 1000;
mod rng;
fn bench_constructors(c: &mut Criterion) {
let values: Vec<i64> = (1..=SIZE as i64).collect();
c.bench_function("seg_tree_new_1000", |b| {
b.iter(|| {
let tree = SegTreeSum::<i64>::new(SIZE);
black_box(&tree);
})
});
c.bench_function("seg_tree_from_slice_1000", |b| {
b.iter(|| {
let tree = SegTreeSum::<i64>::from_slice(&values);
black_box(&tree);
})
});
c.bench_function("seg_tree_from_vec_1000", |b| {
b.iter_batched(
|| values.clone(), |v| {
let tree = SegTreeSum::<i64>::from_vec(v);
black_box(&tree);
},
criterion::BatchSize::SmallInput,
)
});
}
fn bench_range_query(c: &mut Criterion) {
let values: Vec<i64> = (1..=SIZE as i64).collect();
let tree = SegTreeSum::<i64>::from_slice(&values);
let mut rng = rng::Lcg::new(0xC0FFEE);
c.bench_function("seg_tree_range_size_random_query_1000", |b| {
b.iter_batched(
|| {
let left = rng.next_usize(SIZE);
let right = rng.next_usize(SIZE);
if left <= right {
(left, right)
} else {
(right, left)
}
},
|(left, right)| {
let res = tree.query(left..=right);
black_box(res);
},
criterion::BatchSize::SmallInput,
)
});
let window = 750usize;
assert!(window <= SIZE);
c.bench_function("seg_tree_range_size_750_query_1000", |b| {
b.iter_batched(
|| {
let left = rng.next_usize(SIZE - window);
let right = left + window;
(left, right)
},
|(left, right)| {
let res = tree.query(left..=right);
black_box(res);
},
criterion::BatchSize::SmallInput,
)
});
}
fn bench_point_update(c: &mut Criterion) {
let values: Vec<i64> = (1..=SIZE as i64).collect();
let mut tree = SegTreeSum::<i64>::from_vec(values.clone());
let mut rng = rng::Lcg::new(0xFEED_FACE);
c.bench_function("seg_tree_point_update_1000", |b| {
b.iter_batched(
|| {
let idx = rng.next_usize(SIZE);
let val = (rng.next_u64() as i64).wrapping_sub(0x4000_0000_0000_0000u64 as i64);
(idx, val)
},
|(idx, val)| {
tree.update(idx, val);
black_box(&tree);
},
criterion::BatchSize::SmallInput,
)
});
}
fn criterion_config() -> Criterion {
Criterion::default().output_directory(Path::new("target/criterion/seg_tree_1000"))
}
criterion_group! {
name = benches;
config = criterion_config();
targets = bench_constructors,
bench_range_query,
bench_point_update,
}
criterion_main!(benches);