#![feature(test)]
#[macro_use]
extern crate enum_like_derive;
extern crate enum_like;
extern crate enum_vec;
extern crate test;
use self::test::Bencher;
use enum_vec::EnumVec;
use enum_like::EnumLike;
const VEC_SIZE: usize = 16;
const SPILLED_SIZE: usize = 1000;
#[derive(Copy, Clone, Debug, EnumLike)]
enum T2 { A, B, C, D }
impl From<u64> for T2 {
fn from(n: u64) -> Self {
Self::from_discr(n as usize % Self::NUM_VARIANTS)
}
}
trait Vector<T>: Extend<T> {
fn new() -> Self;
fn push(&mut self, val: T);
fn pop(&mut self) -> Option<T>;
fn remove(&mut self, p: usize) -> T;
fn insert(&mut self, n: usize, val: T);
fn from_elem(val: T, n: usize) -> Self;
}
impl<T: Copy + EnumLike> Vector<T> for Vec<T> {
fn new() -> Self {
Self::with_capacity(VEC_SIZE)
}
fn push(&mut self, val: T) {
self.push(val)
}
fn pop(&mut self) -> Option<T> {
self.pop()
}
fn remove(&mut self, p: usize) -> T {
self.remove(p)
}
fn insert(&mut self, n: usize, val: T) {
self.insert(n, val)
}
fn from_elem(val: T, n: usize) -> Self {
vec![val; n]
}
}
impl<T: Copy + EnumLike> Vector<T> for EnumVec<T> {
fn new() -> Self {
Self::new()
}
fn push(&mut self, val: T) {
self.push(val)
}
fn pop(&mut self) -> Option<T> {
self.pop()
}
fn remove(&mut self, p: usize) -> T {
self.remove(p)
}
fn insert(&mut self, n: usize, val: T) {
self.insert(n, val)
}
fn from_elem(val: T, n: usize) -> Self {
let mut ev = EnumVec::new();
ev.resize(n, val);
ev
}
}
macro_rules! make_benches {
($typ:ty { $($b_name:ident => $g_name:ident($($args:expr),*),)* }) => {
$(
#[bench]
fn $b_name(b: &mut Bencher) {
$g_name::<$typ>($($args,)* b)
}
)*
}
}
make_benches! {
EnumVec<T2> {
bench_push => gen_push(SPILLED_SIZE as _),
bench_push_small => gen_push(VEC_SIZE as _),
bench_insert => gen_insert(SPILLED_SIZE as _),
bench_insert_small => gen_insert(VEC_SIZE as _),
bench_remove => gen_remove(SPILLED_SIZE as _),
bench_remove_small => gen_remove(VEC_SIZE as _),
bench_extend => gen_extend(SPILLED_SIZE as _),
bench_extend_small => gen_extend(VEC_SIZE as _),
bench_macro_from_elem => gen_from_elem(SPILLED_SIZE as _),
bench_macro_from_elem_small => gen_from_elem(VEC_SIZE as _),
bench_pushpop => gen_pushpop(),
}
}
make_benches! {
Vec<T2> {
bench_push_vec => gen_push(SPILLED_SIZE as _),
bench_push_vec_small => gen_push(VEC_SIZE as _),
bench_insert_vec => gen_insert(SPILLED_SIZE as _),
bench_insert_vec_small => gen_insert(VEC_SIZE as _),
bench_remove_vec => gen_remove(SPILLED_SIZE as _),
bench_remove_vec_small => gen_remove(VEC_SIZE as _),
bench_extend_vec => gen_extend(SPILLED_SIZE as _),
bench_extend_vec_small => gen_extend(VEC_SIZE as _),
bench_macro_from_elem_vec => gen_from_elem(SPILLED_SIZE as _),
bench_macro_from_elem_vec_small => gen_from_elem(VEC_SIZE as _),
bench_pushpop_vec => gen_pushpop(),
}
}
fn gen_push<V: Vector<T2>>(n: u64, b: &mut Bencher) {
#[inline(never)]
fn push_noinline<V: Vector<T2>>(vec: &mut V, x: T2) {
vec.push(x);
}
b.iter(|| {
let mut vec = V::new();
for x in 0..n {
push_noinline(&mut vec, x.into());
}
vec
});
}
fn gen_insert<V: Vector<T2>>(n: u64, b: &mut Bencher) {
#[inline(never)]
fn insert_noinline<V: Vector<T2>>(vec: &mut V, p: usize, x: T2) {
vec.insert(p, x)
}
b.iter(|| {
let mut vec = V::new();
vec.push(T2::A);
for x in 0..n {
insert_noinline(&mut vec, x as _, x.into());
}
vec
});
}
fn gen_remove<V: Vector<T2>>(n: usize, b: &mut Bencher) {
#[inline(never)]
fn remove_noinline<V: Vector<T2>>(vec: &mut V, p: usize) -> T2 {
vec.remove(p)
}
b.iter(|| {
let mut vec = V::from_elem(T2::C, n as _);
for x in (0..n - 1).rev() {
remove_noinline(&mut vec, x);
}
});
}
fn gen_extend<V: Vector<T2>>(n: u64, b: &mut Bencher) {
let v: Vec<T2> = (0..n).map(|x| x.into()).collect();
b.iter(|| {
let mut vec = V::new();
vec.extend(v.clone());
vec
});
}
fn gen_pushpop<V: Vector<T2>>(b: &mut Bencher) {
#[inline(never)]
fn pushpop_noinline<V: Vector<T2>>(vec: &mut V, x: T2) -> Option<T2> {
vec.push(x);
vec.pop()
}
b.iter(|| {
let mut vec = V::new();
for x in 0..SPILLED_SIZE as _ {
pushpop_noinline(&mut vec, x.into());
}
vec
});
}
fn gen_from_elem<V: Vector<T2>>(n: usize, b: &mut Bencher) {
b.iter(|| {
let vec = V::from_elem(T2::C, n);
vec
});
}