diff options
| author | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2014-06-02 21:56:29 -0700 |
|---|---|---|
| committer | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2014-06-21 17:42:22 -0400 |
| commit | b0fb520f7260d345d6060322ca74b94b00e283d8 (patch) | |
| tree | 8720b4087c9d1497a15b67cf8b99a8e5a38f4190 /src/libcollections | |
| parent | db9af1d505809c965e719bf4ad775ff984ee3da6 (diff) | |
| download | rust-b0fb520f7260d345d6060322ca74b94b00e283d8.tar.gz rust-b0fb520f7260d345d6060322ca74b94b00e283d8.zip | |
std: micro-optimize Vec constructors and add benchmarks
Generally speaking, inlining doesn't really help out with constructing vectors, except for when we construct a zero-sized vector. This patch allows llvm to optimize this case away in a lot of cases, which shaves off 4-8ns. It's not much, but it might help in some inner loop somewhere. before: running 12 tests test bench_extend_0 ... bench: 123 ns/iter (+/- 6) test bench_extend_5 ... bench: 323 ns/iter (+/- 11) test bench_from_fn_0 ... bench: 7 ns/iter (+/- 0) test bench_from_fn_5 ... bench: 49 ns/iter (+/- 6) test bench_from_iter_0 ... bench: 11 ns/iter (+/- 0) test bench_from_iter_5 ... bench: 176 ns/iter (+/- 11) test bench_from_slice_0 ... bench: 8 ns/iter (+/- 1) test bench_from_slice_5 ... bench: 73 ns/iter (+/- 5) test bench_new ... bench: 0 ns/iter (+/- 0) test bench_with_capacity_0 ... bench: 6 ns/iter (+/- 1) test bench_with_capacity_100 ... bench: 41 ns/iter (+/- 3) test bench_with_capacity_5 ... bench: 40 ns/iter (+/- 2) after: test bench_extend_0 ... bench: 123 ns/iter (+/- 7) test bench_extend_5 ... bench: 339 ns/iter (+/- 27) test bench_from_fn_0 ... bench: 7 ns/iter (+/- 0) test bench_from_fn_5 ... bench: 54 ns/iter (+/- 4) test bench_from_iter_0 ... bench: 11 ns/iter (+/- 1) test bench_from_iter_5 ... bench: 182 ns/iter (+/- 16) test bench_from_slice_0 ... bench: 4 ns/iter (+/- 0) test bench_from_slice_5 ... bench: 62 ns/iter (+/- 3) test bench_new ... bench: 0 ns/iter (+/- 0) test bench_with_capacity_0 ... bench: 0 ns/iter (+/- 0) test bench_with_capacity_100 ... bench: 41 ns/iter (+/- 1) test bench_with_capacity_5 ... bench: 41 ns/iter (+/- 3)
Diffstat (limited to 'src/libcollections')
| -rw-r--r-- | src/libcollections/vec.rs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 61e732846a1..53fbed9e11d 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -85,6 +85,7 @@ impl<T> Vec<T> { /// # use std::vec::Vec; /// let vec: Vec<int> = Vec::with_capacity(10); /// ``` + #[inline] pub fn with_capacity(capacity: uint) -> Vec<T> { if mem::size_of::<T>() == 0 { Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T } @@ -110,6 +111,7 @@ impl<T> Vec<T> { /// let vec = Vec::from_fn(3, |idx| idx * 2); /// assert_eq!(vec, vec!(0, 2, 4)); /// ``` + #[inline] pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> { unsafe { let mut xs = Vec::with_capacity(length); @@ -193,6 +195,7 @@ impl<T: Clone> Vec<T> { /// let slice = [1, 2, 3]; /// let vec = Vec::from_slice(slice); /// ``` + #[inline] pub fn from_slice(values: &[T]) -> Vec<T> { values.iter().map(|x| x.clone()).collect() } @@ -207,6 +210,7 @@ impl<T: Clone> Vec<T> { /// let vec = Vec::from_elem(3, "hi"); /// println!("{}", vec); // prints [hi, hi, hi] /// ``` + #[inline] pub fn from_elem(length: uint, value: T) -> Vec<T> { unsafe { let mut xs = Vec::with_capacity(length); @@ -353,6 +357,7 @@ impl<T:Clone> Clone for Vec<T> { } impl<T> FromIterator<T> for Vec<T> { + #[inline] fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> { let (lower, _) = iterator.size_hint(); let mut vector = Vec::with_capacity(lower); @@ -364,6 +369,7 @@ impl<T> FromIterator<T> for Vec<T> { } impl<T> Extendable<T> for Vec<T> { + #[inline] fn extend<I: Iterator<T>>(&mut self, mut iterator: I) { let (lower, _) = iterator.size_hint(); self.reserve_additional(lower); @@ -1029,6 +1035,7 @@ impl<T> Vec<T> { /// vec.push_all_move(vec!(box 2, box 3, box 4)); /// assert_eq!(vec, vec!(box 1, box 2, box 3, box 4)); /// ``` + #[inline] pub fn push_all_move(&mut self, other: Vec<T>) { self.extend(other.move_iter()); } @@ -1306,6 +1313,7 @@ impl<T:PartialEq> Vec<T> { /// let vec = vec!(1, 2, 3); /// assert!(vec.contains(&1)); /// ``` + #[inline] pub fn contains(&self, x: &T) -> bool { self.as_slice().contains(x) } @@ -1836,4 +1844,111 @@ mod tests { let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)]; v.truncate(0); } + + #[bench] + fn bench_new(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::new(); + assert_eq!(v.capacity(), 0); + assert!(v.as_slice() == []); + }) + } + + #[bench] + fn bench_with_capacity_0(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::with_capacity(0); + assert_eq!(v.capacity(), 0); + assert!(v.as_slice() == []); + }) + } + + + #[bench] + fn bench_with_capacity_5(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::with_capacity(5); + assert_eq!(v.capacity(), 5); + assert!(v.as_slice() == []); + }) + } + + #[bench] + fn bench_with_capacity_100(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::with_capacity(100); + assert_eq!(v.capacity(), 100); + assert!(v.as_slice() == []); + }) + } + + #[bench] + fn bench_from_fn_0(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::from_fn(0, |_| 5); + assert!(v.as_slice() == []); + }) + } + + #[bench] + fn bench_from_fn_5(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::from_fn(5, |_| 5); + assert!(v.as_slice() == [5, 5, 5, 5, 5]); + }) + } + + #[bench] + fn bench_from_slice_0(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::from_slice([]); + assert!(v.as_slice() == []); + }) + } + + #[bench] + fn bench_from_slice_5(b: &mut Bencher) { + b.iter(|| { + let v: Vec<int> = Vec::from_slice([1, 2, 3, 4, 5]); + assert!(v.as_slice() == [1, 2, 3, 4, 5]); + }) + } + + #[bench] + fn bench_from_iter_0(b: &mut Bencher) { + b.iter(|| { + let v0: Vec<int> = vec!(); + let v1: Vec<int> = FromIterator::from_iter(v0.move_iter()); + assert!(v1.as_slice() == []); + }) + } + + #[bench] + fn bench_from_iter_5(b: &mut Bencher) { + b.iter(|| { + let v0: Vec<int> = vec!(1, 2, 3, 4, 5); + let v1: Vec<int> = FromIterator::from_iter(v0.move_iter()); + assert!(v1.as_slice() == [1, 2, 3, 4, 5]); + }) + } + + #[bench] + fn bench_extend_0(b: &mut Bencher) { + b.iter(|| { + let v0: Vec<int> = vec!(); + let mut v1: Vec<int> = vec!(1, 2, 3, 4, 5); + v1.extend(v0.move_iter()); + assert!(v1.as_slice() == [1, 2, 3, 4, 5]); + }) + } + + #[bench] + fn bench_extend_5(b: &mut Bencher) { + b.iter(|| { + let v0: Vec<int> = vec!(1, 2, 3, 4, 5); + let mut v1: Vec<int> = vec!(1, 2, 3, 4, 5); + v1.extend(v0.move_iter()); + assert!(v1.as_slice() == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]); + }) + } } |
