about summary refs log tree commit diff
path: root/src/libcollections
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2014-06-02 21:56:29 -0700
committerErick Tryzelaar <erick.tryzelaar@gmail.com>2014-06-21 17:42:22 -0400
commitb0fb520f7260d345d6060322ca74b94b00e283d8 (patch)
tree8720b4087c9d1497a15b67cf8b99a8e5a38f4190 /src/libcollections
parentdb9af1d505809c965e719bf4ad775ff984ee3da6 (diff)
downloadrust-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.rs115
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]);
+        })
+    }
 }