aboutsummaryrefslogtreecommitdiff
path: root/benches
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2020-07-28 13:45:19 -0700
committerJoel Galenson <jgalenson@google.com>2020-07-28 13:45:19 -0700
commitddfee16c0a95c04d30bb80135457bed71dc4b71b (patch)
treeef7ed8a3171cf1906670f6b9fcbf20ef2660852a /benches
parent46d109f968cc3f3d988a0ac7d8b9e0696a29084e (diff)
downloadsmallvec-ddfee16c0a95c04d30bb80135457bed71dc4b71b.tar.gz
Import smallvec-1.4.0
Change-Id: I88441e5cd5fd487e273152f2b28461529b1f368c
Diffstat (limited to 'benches')
-rw-r--r--benches/bench.rs295
1 files changed, 295 insertions, 0 deletions
diff --git a/benches/bench.rs b/benches/bench.rs
new file mode 100644
index 0000000..36cb133
--- /dev/null
+++ b/benches/bench.rs
@@ -0,0 +1,295 @@
+#![feature(test)]
+
+#[macro_use]
+extern crate smallvec;
+extern crate test;
+
+use self::test::Bencher;
+use smallvec::{ExtendFromSlice, SmallVec};
+
+const VEC_SIZE: usize = 16;
+const SPILLED_SIZE: usize = 100;
+
+trait Vector<T>: for<'a> From<&'a [T]> + Extend<T> + ExtendFromSlice<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;
+ fn from_elems(val: &[T]) -> Self;
+}
+
+impl<T: Copy> 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]
+ }
+
+ fn from_elems(val: &[T]) -> Self {
+ val.to_owned()
+ }
+}
+
+impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> {
+ 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 {
+ smallvec![val; n]
+ }
+
+ fn from_elems(val: &[T]) -> Self {
+ SmallVec::from_slice(val)
+ }
+}
+
+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! {
+ SmallVec<[u64; VEC_SIZE]> {
+ 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_from_iter => gen_from_iter(SPILLED_SIZE as _),
+ bench_from_iter_small => gen_from_iter(VEC_SIZE as _),
+ bench_from_slice => gen_from_slice(SPILLED_SIZE as _),
+ bench_from_slice_small => gen_from_slice(VEC_SIZE as _),
+ bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _),
+ bench_extend_from_slice_small => gen_extend_from_slice(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<u64> {
+ 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_from_iter_vec => gen_from_iter(SPILLED_SIZE as _),
+ bench_from_iter_vec_small => gen_from_iter(VEC_SIZE as _),
+ bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _),
+ bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _),
+ bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _),
+ bench_extend_from_slice_vec_small => gen_extend_from_slice(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<u64>>(n: u64, b: &mut Bencher) {
+ #[inline(never)]
+ fn push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) {
+ vec.push(x);
+ }
+
+ b.iter(|| {
+ let mut vec = V::new();
+ for x in 0..n {
+ push_noinline(&mut vec, x);
+ }
+ vec
+ });
+}
+
+fn gen_insert<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+ #[inline(never)]
+ fn insert_noinline<V: Vector<u64>>(vec: &mut V, p: usize, x: u64) {
+ vec.insert(p, x)
+ }
+
+ b.iter(|| {
+ let mut vec = V::new();
+ // Add one element, with each iteration we insert one before the end.
+ // This means that we benchmark the insertion operation and not the
+ // time it takes to `ptr::copy` the data.
+ vec.push(0);
+ for x in 0..n {
+ insert_noinline(&mut vec, x as _, x);
+ }
+ vec
+ });
+}
+
+fn gen_remove<V: Vector<u64>>(n: usize, b: &mut Bencher) {
+ #[inline(never)]
+ fn remove_noinline<V: Vector<u64>>(vec: &mut V, p: usize) -> u64 {
+ vec.remove(p)
+ }
+
+ b.iter(|| {
+ let mut vec = V::from_elem(0, n as _);
+
+ for x in (0..n - 1).rev() {
+ remove_noinline(&mut vec, x);
+ }
+ });
+}
+
+fn gen_extend<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+ b.iter(|| {
+ let mut vec = V::new();
+ vec.extend(0..n);
+ vec
+ });
+}
+
+fn gen_from_iter<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+ let v: Vec<u64> = (0..n).collect();
+ b.iter(|| {
+ let vec = V::from(&v);
+ vec
+ });
+}
+
+fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+ let v: Vec<u64> = (0..n).collect();
+ b.iter(|| {
+ let vec = V::from_elems(&v);
+ vec
+ });
+}
+
+fn gen_extend_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
+ let v: Vec<u64> = (0..n).collect();
+ b.iter(|| {
+ let mut vec = V::new();
+ vec.extend_from_slice(&v);
+ vec
+ });
+}
+
+fn gen_pushpop<V: Vector<u64>>(b: &mut Bencher) {
+ #[inline(never)]
+ fn pushpop_noinline<V: Vector<u64>>(vec: &mut V, x: u64) -> Option<u64> {
+ vec.push(x);
+ vec.pop()
+ }
+
+ b.iter(|| {
+ let mut vec = V::new();
+ for x in 0..SPILLED_SIZE as _ {
+ pushpop_noinline(&mut vec, x);
+ }
+ vec
+ });
+}
+
+fn gen_from_elem<V: Vector<u64>>(n: usize, b: &mut Bencher) {
+ b.iter(|| {
+ let vec = V::from_elem(42, n);
+ vec
+ });
+}
+
+#[bench]
+fn bench_insert_many(b: &mut Bencher) {
+ #[inline(never)]
+ fn insert_many_noinline<I: IntoIterator<Item = u64>>(
+ vec: &mut SmallVec<[u64; VEC_SIZE]>,
+ index: usize,
+ iterable: I,
+ ) {
+ vec.insert_many(index, iterable)
+ }
+
+ b.iter(|| {
+ let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
+ insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _);
+ insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _);
+ vec
+ });
+}
+
+#[bench]
+fn bench_insert_from_slice(b: &mut Bencher) {
+ let v: Vec<u64> = (0..SPILLED_SIZE as _).collect();
+ b.iter(|| {
+ let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
+ vec.insert_from_slice(0, &v);
+ vec.insert_from_slice(0, &v);
+ vec
+ });
+}
+
+#[bench]
+fn bench_macro_from_list(b: &mut Bencher) {
+ b.iter(|| {
+ let vec: SmallVec<[u64; 16]> = smallvec![
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
+ 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
+ 0x80000, 0x100000,
+ ];
+ vec
+ });
+}
+
+#[bench]
+fn bench_macro_from_list_vec(b: &mut Bencher) {
+ b.iter(|| {
+ let vec: Vec<u64> = vec![
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
+ 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
+ 0x80000, 0x100000,
+ ];
+ vec
+ });
+}