Skip to content

Commit cc31d1e

Browse files
committed
Add benchmarks for smallvec when it's on the stack
1 parent 291eb90 commit cc31d1e

File tree

2 files changed

+138
-133
lines changed

2 files changed

+138
-133
lines changed

benches/bench.rs

Lines changed: 137 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -4,213 +4,218 @@
44
extern crate smallvec;
55
extern crate test;
66

7-
use smallvec::SmallVec;
87
use self::test::Bencher;
8+
use smallvec::{ExtendFromSlice, SmallVec};
99

10-
#[bench]
11-
fn bench_push(b: &mut Bencher) {
12-
#[inline(never)]
13-
fn push_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) {
14-
vec.push(x)
15-
}
10+
const VEC_SIZE: usize = 16;
1611

17-
b.iter(|| {
18-
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
19-
for x in 0..100 {
20-
push_noinline(&mut vec, x);
21-
}
22-
vec
23-
});
12+
trait Vector<T>: for<'a> From<&'a [T]> + Extend<T> + ExtendFromSlice<T> {
13+
fn new() -> Self;
14+
fn push(&mut self, val: T);
15+
fn pop(&mut self) -> Option<T>;
16+
fn insert(&mut self, n: usize, val: T);
17+
fn from_elem(val: T, n: usize) -> Self;
2418
}
2519

26-
#[bench]
27-
fn bench_insert(b: &mut Bencher) {
28-
#[inline(never)]
29-
fn insert_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) {
30-
vec.insert(0, x)
20+
impl<T: Copy> Vector<T> for Vec<T> {
21+
fn new() -> Self {
22+
Self::with_capacity(VEC_SIZE)
23+
}
24+
fn push(&mut self, val: T) {
25+
self.push(val)
26+
}
27+
fn pop(&mut self) -> Option<T> {
28+
self.pop()
29+
}
30+
fn insert(&mut self, n: usize, val: T) {
31+
self.insert(n, val)
32+
}
33+
fn from_elem(val: T, n: usize) -> Self {
34+
vec![val; n]
3135
}
32-
33-
b.iter(|| {
34-
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
35-
for x in 0..100 {
36-
insert_noinline(&mut vec, x);
37-
}
38-
vec
39-
});
4036
}
4137

42-
#[bench]
43-
fn bench_insert_many(b: &mut Bencher) {
44-
#[inline(never)]
45-
fn insert_many_noinline<I: IntoIterator<Item=u64>>(
46-
vec: &mut SmallVec<[u64; 16]>, index: usize, iterable: I) {
47-
vec.insert_many(index, iterable)
38+
impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> {
39+
fn new() -> Self {
40+
Self::new()
41+
}
42+
fn push(&mut self, val: T) {
43+
self.push(val)
44+
}
45+
fn pop(&mut self) -> Option<T> {
46+
self.pop()
47+
}
48+
fn insert(&mut self, n: usize, val: T) {
49+
self.insert(n, val)
50+
}
51+
fn from_elem(val: T, n: usize) -> Self {
52+
smallvec![val; n]
4853
}
49-
50-
b.iter(|| {
51-
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
52-
insert_many_noinline(&mut vec, 0, 0..100);
53-
insert_many_noinline(&mut vec, 0, 0..100);
54-
vec
55-
});
5654
}
5755

58-
#[bench]
59-
fn bench_extend(b: &mut Bencher) {
60-
b.iter(|| {
61-
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
62-
vec.extend(0..100);
63-
vec
64-
});
56+
macro_rules! make_benches {
57+
($typ:ty { $($b_name:ident => $g_name:ident($($args:expr),*),)* }) => {
58+
$(
59+
#[bench]
60+
fn $b_name(b: &mut Bencher) {
61+
$g_name::<$typ>($($args,)* b)
62+
}
63+
)*
64+
}
6565
}
6666

67-
#[bench]
68-
fn bench_from_slice(b: &mut Bencher) {
69-
let v: Vec<u64> = (0..100).collect();
70-
b.iter(|| {
71-
let vec: SmallVec<[u64; 16]> = SmallVec::from_slice(&v);
72-
vec
73-
});
67+
make_benches! {
68+
SmallVec<[u64; VEC_SIZE]> {
69+
bench_push => gen_push(100),
70+
bench_push_small => gen_push(VEC_SIZE as _),
71+
bench_insert => gen_insert(100),
72+
bench_insert_small => gen_insert(VEC_SIZE as _),
73+
bench_extend => gen_extend(100),
74+
bench_extend_small => gen_extend(VEC_SIZE as _),
75+
bench_from_slice => gen_from_slice(100),
76+
bench_from_slice_small => gen_from_slice(VEC_SIZE as _),
77+
bench_extend_from_slice => gen_extend_from_slice(100),
78+
bench_extend_from_slice_small => gen_extend_from_slice(VEC_SIZE as _),
79+
bench_macro_from_elem => gen_from_elem(100),
80+
bench_macro_from_elem_small => gen_from_elem(VEC_SIZE as _),
81+
bench_pushpop => gen_pushpop(),
82+
}
7483
}
7584

76-
#[bench]
77-
fn bench_extend_from_slice(b: &mut Bencher) {
78-
let v: Vec<u64> = (0..100).collect();
79-
b.iter(|| {
80-
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
81-
vec.extend_from_slice(&v);
82-
vec
83-
});
85+
make_benches! {
86+
Vec<u64> {
87+
bench_push_vec => gen_push(100),
88+
bench_push_vec_small => gen_push(VEC_SIZE as _),
89+
bench_insert_vec => gen_insert(100),
90+
bench_insert_vec_small => gen_insert(VEC_SIZE as _),
91+
bench_extend_vec => gen_extend(100),
92+
bench_extend_vec_small => gen_extend(VEC_SIZE as _),
93+
bench_from_slice_vec => gen_from_slice(100),
94+
bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _),
95+
bench_extend_from_slice_vec => gen_extend_from_slice(100),
96+
bench_extend_from_slice_vec_small => gen_extend_from_slice(VEC_SIZE as _),
97+
bench_macro_from_elem_vec => gen_from_elem(100),
98+
bench_macro_from_elem_vec_small => gen_from_elem(VEC_SIZE as _),
99+
bench_pushpop_vec => gen_pushpop(),
100+
}
84101
}
85102

86-
#[bench]
87-
fn bench_insert_from_slice(b: &mut Bencher) {
88-
let v: Vec<u64> = (0..100).collect();
103+
fn gen_push<V: Vector<u64>>(n: u64, b: &mut Bencher) {
104+
#[inline(never)]
105+
fn push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) {
106+
vec.push(x);
107+
}
108+
89109
b.iter(|| {
90-
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
91-
vec.insert_from_slice(0, &v);
92-
vec.insert_from_slice(0, &v);
110+
let mut vec = V::new();
111+
for x in 0..n {
112+
push_noinline(&mut vec, x);
113+
}
93114
vec
94115
});
95116
}
96117

97-
#[bench]
98-
fn bench_pushpop(b: &mut Bencher) {
118+
fn gen_insert<V: Vector<u64>>(n: u64, b: &mut Bencher) {
99119
#[inline(never)]
100-
fn pushpop_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) {
101-
vec.push(x);
102-
vec.pop();
120+
fn insert_noinline<V: Vector<u64>>(vec: &mut V, x: u64) {
121+
vec.insert(0, x)
103122
}
104123

105124
b.iter(|| {
106-
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
107-
for x in 0..100 {
108-
pushpop_noinline(&mut vec, x);
125+
let mut vec = V::new();
126+
for x in 0..n {
127+
insert_noinline(&mut vec, x);
109128
}
110129
vec
111130
});
112131
}
113132

114-
#[bench]
115-
fn bench_macro_from_elem(b: &mut Bencher) {
133+
fn gen_extend<V: Vector<u64>>(n: u64, b: &mut Bencher) {
116134
b.iter(|| {
117-
let vec: SmallVec<[u64; 16]> = smallvec![42; 100];
135+
let mut vec = V::new();
136+
vec.extend(0..n);
118137
vec
119138
});
120139
}
121140

122-
#[bench]
123-
fn bench_macro_from_list(b: &mut Bencher) {
141+
fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
142+
let v: Vec<u64> = (0..n).collect();
124143
b.iter(|| {
125-
let vec: SmallVec<[u64; 16]> = smallvec![
126-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
127-
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
128-
0x80000, 0x100000
129-
];
144+
let vec = V::from(&v);
130145
vec
131146
});
132147
}
133-
#[bench]
134-
fn bench_push_vec(b: &mut Bencher) {
135-
#[inline(never)]
136-
fn push_noinline(vec: &mut Vec<u64>, x: u64) {
137-
vec.push(x)
138-
}
139148

149+
fn gen_extend_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
150+
let v: Vec<u64> = (0..n).collect();
140151
b.iter(|| {
141-
let mut vec: Vec<u64> = Vec::with_capacity(16);
142-
for x in 0..100 {
143-
push_noinline(&mut vec, x);
144-
}
152+
let mut vec = V::new();
153+
vec.extend_from_slice(&v);
145154
vec
146155
});
147156
}
148157

149-
#[bench]
150-
fn bench_insert_vec(b: &mut Bencher) {
158+
fn gen_pushpop<V: Vector<u64>>(b: &mut Bencher) {
151159
#[inline(never)]
152-
fn insert_noinline(vec: &mut Vec<u64>, x: u64) {
153-
vec.insert(0, x)
160+
fn pushpop_noinline<V: Vector<u64>>(vec: &mut V, x: u64) {
161+
vec.push(x);
162+
vec.pop();
154163
}
155164

156165
b.iter(|| {
157-
let mut vec: Vec<u64> = Vec::with_capacity(16);
166+
let mut vec = V::new();
158167
for x in 0..100 {
159-
insert_noinline(&mut vec, x);
168+
pushpop_noinline(&mut vec, x);
160169
}
161170
vec
162171
});
163172
}
164173

165-
#[bench]
166-
fn bench_extend_vec(b: &mut Bencher) {
174+
fn gen_from_elem<V: Vector<u64>>(n: usize, b: &mut Bencher) {
167175
b.iter(|| {
168-
let mut vec: Vec<u64> = Vec::with_capacity(16);
169-
vec.extend(0..100);
176+
let vec = V::from_elem(42, n);
170177
vec
171178
});
172179
}
173180

174181
#[bench]
175-
fn bench_from_slice_vec(b: &mut Bencher) {
176-
let v: Vec<u64> = (0..100).collect();
177-
b.iter(|| {
178-
let vec: Vec<u64> = Vec::from(&v[..]);
179-
vec
180-
});
181-
}
182+
fn bench_insert_many(b: &mut Bencher) {
183+
#[inline(never)]
184+
fn insert_many_noinline<I: IntoIterator<Item = u64>>(
185+
vec: &mut SmallVec<[u64; VEC_SIZE]>,
186+
index: usize,
187+
iterable: I,
188+
) {
189+
vec.insert_many(index, iterable)
190+
}
182191

183-
#[bench]
184-
fn bench_extend_from_slice_vec(b: &mut Bencher) {
185-
let v: Vec<u64> = (0..100).collect();
186192
b.iter(|| {
187-
let mut vec: Vec<u64> = Vec::with_capacity(16);
188-
vec.extend_from_slice(&v);
193+
let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
194+
insert_many_noinline(&mut vec, 0, 0..100);
195+
insert_many_noinline(&mut vec, 0, 0..100);
189196
vec
190197
});
191198
}
192199

193200
#[bench]
194-
fn bench_pushpop_vec(b: &mut Bencher) {
195-
#[inline(never)]
196-
fn pushpop_noinline(vec: &mut Vec<u64>, x: u64) {
197-
vec.push(x);
198-
vec.pop();
199-
}
200-
201+
fn bench_insert_from_slice(b: &mut Bencher) {
202+
let v: Vec<u64> = (0..100).collect();
201203
b.iter(|| {
202-
let mut vec: Vec<u64> = Vec::with_capacity(16);
203-
for x in 0..100 {
204-
pushpop_noinline(&mut vec, x);
205-
}
204+
let mut vec = SmallVec::<[u64; VEC_SIZE]>::new();
205+
vec.insert_from_slice(0, &v);
206+
vec.insert_from_slice(0, &v);
206207
vec
207208
});
208209
}
209210

210211
#[bench]
211-
fn bench_macro_from_elem_vec(b: &mut Bencher) {
212+
fn bench_macro_from_list(b: &mut Bencher) {
212213
b.iter(|| {
213-
let vec: Vec<u64> = vec![42; 100];
214+
let vec: SmallVec<[u64; 16]> = smallvec![
215+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
216+
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
217+
0x80000, 0x100000,
218+
];
214219
vec
215220
});
216221
}
@@ -221,7 +226,7 @@ fn bench_macro_from_list_vec(b: &mut Bencher) {
221226
let vec: Vec<u64> = vec![
222227
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80,
223228
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
224-
0x80000, 0x100000
229+
0x80000, 0x100000,
225230
];
226231
vec
227232
});

lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ macro_rules! smallvec {
9999
($elem:expr; $n:expr) => ({
100100
SmallVec::from_elem($elem, $n)
101101
});
102-
($($x:expr),*) => ({
102+
($($x:expr),*$(,)*) => ({
103103
SmallVec::from_slice(&[$($x),*])
104104
});
105105
}

0 commit comments

Comments
 (0)