Skip to content

Commit 8163251

Browse files
committed
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.
1 parent b6933f8 commit 8163251

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

src/libstd/vec.rs

+31-9
Original file line numberDiff line numberDiff line change
@@ -1661,20 +1661,28 @@ impl<T> OwnedVector<T> for ~[T] {
16611661
}
16621662

16631663
fn unshift(&mut self, x: T) {
1664-
let v = util::replace(self, ~[x]);
1665-
self.push_all_move(v);
1664+
self.insert(0, x)
16661665
}
1667-
fn insert(&mut self, i: uint, x:T) {
1666+
1667+
fn insert(&mut self, i: uint, x: T) {
16681668
let len = self.len();
16691669
assert!(i <= len);
1670-
1671-
self.push(x);
1672-
let mut j = len;
1673-
while j > i {
1674-
self.swap(j, j - 1);
1675-
j -= 1;
1670+
// space for the new element
1671+
self.reserve_additional(1);
1672+
1673+
unsafe { // infallible
1674+
// The spot to put the new value
1675+
let p = self.as_mut_ptr().offset(i as int);
1676+
// Shift everything over to make space. (Duplicating the
1677+
// `i`th element into two consecutive places.)
1678+
ptr::copy_memory(p.offset(1), p, len - i);
1679+
// Write it in, overwriting the first copy of the `i`th
1680+
// element.
1681+
intrinsics::move_val_init(&mut *p, x);
1682+
self.set_len(len + 1);
16761683
}
16771684
}
1685+
16781686
fn remove(&mut self, i: uint) -> T {
16791687
let len = self.len();
16801688
assert!(i < len);
@@ -4144,6 +4152,7 @@ mod bench {
41444152
use vec::VectorVector;
41454153
use option::*;
41464154
use ptr;
4155+
use rand::{weak_rng, Rng};
41474156

41484157
#[bench]
41494158
fn iterator(bh: &mut BenchHarness) {
@@ -4320,4 +4329,17 @@ mod bench {
43204329
}
43214330
});
43224331
}
4332+
4333+
#[bench]
4334+
fn random_inserts(bh: &mut BenchHarness) {
4335+
let mut rng = weak_rng();
4336+
bh.iter(|| {
4337+
let mut v = vec::from_elem(30, (0u, 0u));
4338+
for _ in range(0, 100) {
4339+
let l = v.len();
4340+
v.insert(rng.gen::<uint>() % (l + 1),
4341+
(1, 1));
4342+
}
4343+
})
4344+
}
43234345
}

0 commit comments

Comments
 (0)