1 | #![feature (test)] |
2 | #![allow (deprecated)] |
3 | |
4 | extern crate test; |
5 | |
6 | use self::test::Bencher; |
7 | use smallvec::{ExtendFromSlice, smallvec, SmallVec}; |
8 | |
9 | const VEC_SIZE: usize = 16; |
10 | const SPILLED_SIZE: usize = 100; |
11 | |
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 remove(&mut self, p: usize) -> T; |
17 | fn insert(&mut self, n: usize, val: T); |
18 | fn from_elem(val: T, n: usize) -> Self; |
19 | fn from_elems(val: &[T]) -> Self; |
20 | } |
21 | |
22 | impl<T: Copy> Vector<T> for Vec<T> { |
23 | fn new() -> Self { |
24 | Self::with_capacity(VEC_SIZE) |
25 | } |
26 | |
27 | fn push(&mut self, val: T) { |
28 | self.push(val) |
29 | } |
30 | |
31 | fn pop(&mut self) -> Option<T> { |
32 | self.pop() |
33 | } |
34 | |
35 | fn remove(&mut self, p: usize) -> T { |
36 | self.remove(p) |
37 | } |
38 | |
39 | fn insert(&mut self, n: usize, val: T) { |
40 | self.insert(n, val) |
41 | } |
42 | |
43 | fn from_elem(val: T, n: usize) -> Self { |
44 | vec![val; n] |
45 | } |
46 | |
47 | fn from_elems(val: &[T]) -> Self { |
48 | val.to_owned() |
49 | } |
50 | } |
51 | |
52 | impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> { |
53 | fn new() -> Self { |
54 | Self::new() |
55 | } |
56 | |
57 | fn push(&mut self, val: T) { |
58 | self.push(val) |
59 | } |
60 | |
61 | fn pop(&mut self) -> Option<T> { |
62 | self.pop() |
63 | } |
64 | |
65 | fn remove(&mut self, p: usize) -> T { |
66 | self.remove(p) |
67 | } |
68 | |
69 | fn insert(&mut self, n: usize, val: T) { |
70 | self.insert(n, val) |
71 | } |
72 | |
73 | fn from_elem(val: T, n: usize) -> Self { |
74 | smallvec![val; n] |
75 | } |
76 | |
77 | fn from_elems(val: &[T]) -> Self { |
78 | SmallVec::from_slice(val) |
79 | } |
80 | } |
81 | |
82 | macro_rules! make_benches { |
83 | ($typ:ty { $($b_name:ident => $g_name:ident($($args:expr),*),)* }) => { |
84 | $( |
85 | #[bench] |
86 | fn $b_name(b: &mut Bencher) { |
87 | $g_name::<$typ>($($args,)* b) |
88 | } |
89 | )* |
90 | } |
91 | } |
92 | |
93 | make_benches! { |
94 | SmallVec<[u64; VEC_SIZE]> { |
95 | bench_push => gen_push(SPILLED_SIZE as _), |
96 | bench_push_small => gen_push(VEC_SIZE as _), |
97 | bench_insert_push => gen_insert_push(SPILLED_SIZE as _), |
98 | bench_insert_push_small => gen_insert_push(VEC_SIZE as _), |
99 | bench_insert => gen_insert(SPILLED_SIZE as _), |
100 | bench_insert_small => gen_insert(VEC_SIZE as _), |
101 | bench_remove => gen_remove(SPILLED_SIZE as _), |
102 | bench_remove_small => gen_remove(VEC_SIZE as _), |
103 | bench_extend => gen_extend(SPILLED_SIZE as _), |
104 | bench_extend_small => gen_extend(VEC_SIZE as _), |
105 | bench_from_iter => gen_from_iter(SPILLED_SIZE as _), |
106 | bench_from_iter_small => gen_from_iter(VEC_SIZE as _), |
107 | bench_from_slice => gen_from_slice(SPILLED_SIZE as _), |
108 | bench_from_slice_small => gen_from_slice(VEC_SIZE as _), |
109 | bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _), |
110 | bench_extend_from_slice_small => gen_extend_from_slice(VEC_SIZE as _), |
111 | bench_macro_from_elem => gen_from_elem(SPILLED_SIZE as _), |
112 | bench_macro_from_elem_small => gen_from_elem(VEC_SIZE as _), |
113 | bench_pushpop => gen_pushpop(), |
114 | } |
115 | } |
116 | |
117 | make_benches! { |
118 | Vec<u64> { |
119 | bench_push_vec => gen_push(SPILLED_SIZE as _), |
120 | bench_push_vec_small => gen_push(VEC_SIZE as _), |
121 | bench_insert_push_vec => gen_insert_push(SPILLED_SIZE as _), |
122 | bench_insert_push_vec_small => gen_insert_push(VEC_SIZE as _), |
123 | bench_insert_vec => gen_insert(SPILLED_SIZE as _), |
124 | bench_insert_vec_small => gen_insert(VEC_SIZE as _), |
125 | bench_remove_vec => gen_remove(SPILLED_SIZE as _), |
126 | bench_remove_vec_small => gen_remove(VEC_SIZE as _), |
127 | bench_extend_vec => gen_extend(SPILLED_SIZE as _), |
128 | bench_extend_vec_small => gen_extend(VEC_SIZE as _), |
129 | bench_from_iter_vec => gen_from_iter(SPILLED_SIZE as _), |
130 | bench_from_iter_vec_small => gen_from_iter(VEC_SIZE as _), |
131 | bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _), |
132 | bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _), |
133 | bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _), |
134 | bench_extend_from_slice_vec_small => gen_extend_from_slice(VEC_SIZE as _), |
135 | bench_macro_from_elem_vec => gen_from_elem(SPILLED_SIZE as _), |
136 | bench_macro_from_elem_vec_small => gen_from_elem(VEC_SIZE as _), |
137 | bench_pushpop_vec => gen_pushpop(), |
138 | } |
139 | } |
140 | |
141 | fn gen_push<V: Vector<u64>>(n: u64, b: &mut Bencher) { |
142 | #[inline (never)] |
143 | fn push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) { |
144 | vec.push(x); |
145 | } |
146 | |
147 | b.iter(|| { |
148 | let mut vec = V::new(); |
149 | for x in 0..n { |
150 | push_noinline(&mut vec, x); |
151 | } |
152 | vec |
153 | }); |
154 | } |
155 | |
156 | fn gen_insert_push<V: Vector<u64>>(n: u64, b: &mut Bencher) { |
157 | #[inline (never)] |
158 | fn insert_push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) { |
159 | vec.insert(x as usize, x); |
160 | } |
161 | |
162 | b.iter(|| { |
163 | let mut vec = V::new(); |
164 | for x in 0..n { |
165 | insert_push_noinline(&mut vec, x); |
166 | } |
167 | vec |
168 | }); |
169 | } |
170 | |
171 | fn gen_insert<V: Vector<u64>>(n: u64, b: &mut Bencher) { |
172 | #[inline (never)] |
173 | fn insert_noinline<V: Vector<u64>>(vec: &mut V, p: usize, x: u64) { |
174 | vec.insert(p, x) |
175 | } |
176 | |
177 | b.iter(|| { |
178 | let mut vec = V::new(); |
179 | // Always insert at position 0 so that we are subject to shifts of |
180 | // many different lengths. |
181 | vec.push(0); |
182 | for x in 0..n { |
183 | insert_noinline(&mut vec, 0, x); |
184 | } |
185 | vec |
186 | }); |
187 | } |
188 | |
189 | fn gen_remove<V: Vector<u64>>(n: usize, b: &mut Bencher) { |
190 | #[inline (never)] |
191 | fn remove_noinline<V: Vector<u64>>(vec: &mut V, p: usize) -> u64 { |
192 | vec.remove(p) |
193 | } |
194 | |
195 | b.iter(|| { |
196 | let mut vec = V::from_elem(0, n as _); |
197 | |
198 | for _ in 0..n { |
199 | remove_noinline(&mut vec, 0); |
200 | } |
201 | }); |
202 | } |
203 | |
204 | fn gen_extend<V: Vector<u64>>(n: u64, b: &mut Bencher) { |
205 | b.iter(|| { |
206 | let mut vec = V::new(); |
207 | vec.extend(0..n); |
208 | vec |
209 | }); |
210 | } |
211 | |
212 | fn gen_from_iter<V: Vector<u64>>(n: u64, b: &mut Bencher) { |
213 | let v: Vec<u64> = (0..n).collect(); |
214 | b.iter(|| { |
215 | let vec = V::from(&v); |
216 | vec |
217 | }); |
218 | } |
219 | |
220 | fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) { |
221 | let v: Vec<u64> = (0..n).collect(); |
222 | b.iter(|| { |
223 | let vec = V::from_elems(&v); |
224 | vec |
225 | }); |
226 | } |
227 | |
228 | fn gen_extend_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) { |
229 | let v: Vec<u64> = (0..n).collect(); |
230 | b.iter(|| { |
231 | let mut vec = V::new(); |
232 | vec.extend_from_slice(&v); |
233 | vec |
234 | }); |
235 | } |
236 | |
237 | fn gen_pushpop<V: Vector<u64>>(b: &mut Bencher) { |
238 | #[inline (never)] |
239 | fn pushpop_noinline<V: Vector<u64>>(vec: &mut V, x: u64) -> Option<u64> { |
240 | vec.push(x); |
241 | vec.pop() |
242 | } |
243 | |
244 | b.iter(|| { |
245 | let mut vec = V::new(); |
246 | for x in 0..SPILLED_SIZE as _ { |
247 | pushpop_noinline(&mut vec, x); |
248 | } |
249 | vec |
250 | }); |
251 | } |
252 | |
253 | fn gen_from_elem<V: Vector<u64>>(n: usize, b: &mut Bencher) { |
254 | b.iter(|| { |
255 | let vec = V::from_elem(42, n); |
256 | vec |
257 | }); |
258 | } |
259 | |
260 | #[bench] |
261 | fn bench_insert_many(b: &mut Bencher) { |
262 | #[inline (never)] |
263 | fn insert_many_noinline<I: IntoIterator<Item = u64>>( |
264 | vec: &mut SmallVec<[u64; VEC_SIZE]>, |
265 | index: usize, |
266 | iterable: I, |
267 | ) { |
268 | vec.insert_many(index, iterable) |
269 | } |
270 | |
271 | b.iter(|| { |
272 | let mut vec = SmallVec::<[u64; VEC_SIZE]>::new(); |
273 | insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _); |
274 | insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _); |
275 | vec |
276 | }); |
277 | } |
278 | |
279 | #[bench] |
280 | fn bench_insert_from_slice(b: &mut Bencher) { |
281 | let v: Vec<u64> = (0..SPILLED_SIZE as _).collect(); |
282 | b.iter(|| { |
283 | let mut vec = SmallVec::<[u64; VEC_SIZE]>::new(); |
284 | vec.insert_from_slice(0, &v); |
285 | vec.insert_from_slice(0, &v); |
286 | vec |
287 | }); |
288 | } |
289 | |
290 | #[bench] |
291 | fn bench_macro_from_list(b: &mut Bencher) { |
292 | b.iter(|| { |
293 | let vec: SmallVec<[u64; 16]> = smallvec![ |
294 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, |
295 | 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, |
296 | 0x80000, 0x100000, |
297 | ]; |
298 | vec |
299 | }); |
300 | } |
301 | |
302 | #[bench] |
303 | fn bench_macro_from_list_vec(b: &mut Bencher) { |
304 | b.iter(|| { |
305 | let vec: Vec<u64> = vec![ |
306 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, |
307 | 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, |
308 | 0x80000, 0x100000, |
309 | ]; |
310 | vec |
311 | }); |
312 | } |
313 | |