about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-12-19 13:23:37 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2013-12-19 14:00:44 +1100
commit81632513c13495fd269082d35916ebcd91d15658 (patch)
tree3115d8965dcb8baca15748a7839c07868677da07 /src/libstd
parentb6933f8d8b86f78ac7b5f70f0781d794144763a0 (diff)
downloadrust-81632513c13495fd269082d35916ebcd91d15658.tar.gz
rust-81632513c13495fd269082d35916ebcd91d15658.zip
std::vec: replace .insert with a small amount of unsafe code.
This makes the included benchmark more than 3 times faster. Also,
`.unshift(x)` is now faster as `.insert(0, x)` which can reuse the
allocation if necessary.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/vec.rs40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 65be214c14e..e58be99e564 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -1661,20 +1661,28 @@ impl<T> OwnedVector<T> for ~[T] {
     }
 
     fn unshift(&mut self, x: T) {
-        let v = util::replace(self, ~[x]);
-        self.push_all_move(v);
+        self.insert(0, x)
     }
-    fn insert(&mut self, i: uint, x:T) {
+
+    fn insert(&mut self, i: uint, x: T) {
         let len = self.len();
         assert!(i <= len);
-
-        self.push(x);
-        let mut j = len;
-        while j > i {
-            self.swap(j, j - 1);
-            j -= 1;
+        // space for the new element
+        self.reserve_additional(1);
+
+        unsafe { // infallible
+            // The spot to put the new value
+            let p = self.as_mut_ptr().offset(i as int);
+            // Shift everything over to make space. (Duplicating the
+            // `i`th element into two consecutive places.)
+            ptr::copy_memory(p.offset(1), p, len - i);
+            // Write it in, overwriting the first copy of the `i`th
+            // element.
+            intrinsics::move_val_init(&mut *p, x);
+            self.set_len(len + 1);
         }
     }
+
     fn remove(&mut self, i: uint) -> T {
         let len = self.len();
         assert!(i < len);
@@ -4144,6 +4152,7 @@ mod bench {
     use vec::VectorVector;
     use option::*;
     use ptr;
+    use rand::{weak_rng, Rng};
 
     #[bench]
     fn iterator(bh: &mut BenchHarness) {
@@ -4320,4 +4329,17 @@ mod bench {
             }
         });
     }
+
+    #[bench]
+    fn random_inserts(bh: &mut BenchHarness) {
+        let mut rng = weak_rng();
+        bh.iter(|| {
+                let mut v = vec::from_elem(30, (0u, 0u));
+                for _ in range(0, 100) {
+                    let l = v.len();
+                    v.insert(rng.gen::<uint>() % (l + 1),
+                             (1, 1));
+                }
+            })
+    }
 }