use criterion::{black_box, criterion_group, criterion_main, Criterion};
use slicefire::*;
/// Sequentially write `value` into `slice` with the given `indices`
pub fn writes<T: Copy>(slice: &mut [T], value: T, indices: &[usize]) -> bool {
for i in indices {
if *i >= slice.len() {
return false;
}
}
for i in indices {
slice[*i] = value;
}
true
}
/// Sequentially write `value` into `slice` with the given `indices`, discarding
/// the writes for any out of bound indexes
pub fn writes_discard<T: Copy>(vs: &mut [T], val: T, indices: &[usize]) {
for i in indices {
if *i < vs.len() {
vs[*i] = val;
}
}
}
#[derive(Debug, Copy, Clone)]
#[allow(unused)]
struct Foo {
x: i32,
y: i64,
}
impl From<i32> for Foo {
fn from(x: i32) -> Self {
Self { x, y: x as i64 * 2 }
}
}
fn indices(size: usize) -> (Vec<usize>, Vec<Foo>) {
let indices = (0..(size)).map(|i| i % (size - 2)).collect::<Vec<usize>>();
let vs = (0..size).map(|v| (v as i32).into()).collect::<Vec<Foo>>();
(indices, vs)
}
fn write_single_value_with_size(size: usize, c: &mut Criterion) {
let (indices, mut vs) = indices(size);
let val = black_box(Foo::from(10));
c.bench_function(&format!("writes {}", size), |b| {
b.iter(|| writes(&mut vs, black_box(val), &indices))
});
c.bench_function(&format!("writes_discard {}", size), |b| {
b.iter(|| writes_discard(&mut vs, black_box(val), &indices))
});
c.bench_function(&format!("writes_par {}", size), |b| {
b.iter(|| writes_par(&mut vs, black_box(val), &indices))
});
c.bench_function(&format!("writes_par_discard {}", size), |b| {
b.iter(|| writes_par_discard(&mut vs, black_box(val), &indices))
});
}
fn write_values_with_size(size: usize, c: &mut Criterion) {
let (indices, mut vs) = indices(size);
let vals = (0..20).map(|v| v.into()).collect::<Vec<Foo>>();
let vals = &vals;
c.bench_function(&format!("writes vals {}", size), |b| {
b.iter(|| {
for val in vals {
writes(&mut vs, black_box(*val), &indices);
}
})
});
c.bench_function(&format!("write_discards vals {}", size), |b| {
b.iter(|| {
for val in vals {
writes_discard(&mut vs, black_box(*val), &indices);
}
})
});
c.bench_function(&format!("writes_par vals {}", size), |b| {
b.iter(|| {
for val in vals {
writes_par(&mut vs, black_box(*val), &indices);
}
})
});
c.bench_function(&format!("writes_par_discard vals {}", size), |b| {
b.iter(|| {
for val in vals {
writes_par_discard(&mut vs, black_box(*val), &indices);
}
})
});
}
fn write_values(c: &mut Criterion) {
write_values_with_size(1_000, c);
write_values_with_size(10_000, c);
write_values_with_size(100_000, c);
}
fn write_single_value(c: &mut Criterion) {
write_single_value_with_size(1_000, c);
write_single_value_with_size(10_000, c);
write_single_value_with_size(100_000, c);
}
criterion_group!(benches, write_single_value, write_values);
criterion_main!(benches);