Skip to content

Commit e86cdaf

Browse files
committed
auto merge of #11061 : huonw/rust/opt-unsafe-vec, r=alexcrichton
Before: ``` test vec::bench::random_inserts ... bench: 15025 ns/iter (+/- 409) test vec::bench::random_removes ... bench: 16063 ns/iter (+/- 276) ``` After: ``` test vec::bench::random_inserts ... bench: 5257 ns/iter (+/- 321) test vec::bench::random_removes ... bench: 4980 ns/iter (+/- 94) ```
2 parents b3cee62 + acd2be4 commit e86cdaf

File tree

1 file changed

+105
-48
lines changed

1 file changed

+105
-48
lines changed

src/libstd/vec.rs

+105-48
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,22 @@ pub trait OwnedVector<T> {
14001400
/// elements after position i one position to the right.
14011401
fn insert(&mut self, i: uint, x:T);
14021402

1403+
/// Remove and return the element at position `i` within `v`,
1404+
/// shifting all elements after position `i` one position to the
1405+
/// left. Returns `None` if `i` is out of bounds.
1406+
///
1407+
/// # Example
1408+
/// ```rust
1409+
/// let mut v = ~[1, 2, 3];
1410+
/// assert_eq!(v.remove_opt(1), Some(2));
1411+
/// assert_eq!(v, ~[1, 3]);
1412+
///
1413+
/// assert_eq!(v.remove_opt(4), None);
1414+
/// // v is unchanged:
1415+
/// assert_eq!(v, ~[1, 3]);
1416+
/// ```
1417+
fn remove_opt(&mut self, i: uint) -> Option<T>;
1418+
14031419
/// Remove and return the element at position i within v, shifting
14041420
/// all elements after position i one position to the left.
14051421
fn remove(&mut self, i: uint) -> T;
@@ -1609,66 +1625,59 @@ impl<T> OwnedVector<T> for ~[T] {
16091625
}
16101626

16111627
fn shift_opt(&mut self) -> Option<T> {
1612-
match self.len() {
1613-
0 => None,
1614-
1 => self.pop_opt(),
1615-
2 => {
1616-
let last = self.pop();
1617-
let first = self.pop_opt();
1618-
self.push(last);
1619-
first
1620-
}
1621-
len => {
1622-
unsafe {
1623-
let next_len = len - 1;
1624-
1625-
let ptr = self.as_ptr();
1626-
1627-
// copy out the head element, for the moment it exists
1628-
// unsafely on the stack and as the first element of the
1629-
// vector.
1630-
let head = ptr::read_ptr(ptr);
1631-
1632-
// Memcpy everything to the left one element (leaving the
1633-
// last element unsafely in two consecutive memory
1634-
// locations)
1635-
ptr::copy_memory(self.as_mut_ptr(), ptr.offset(1), next_len);
1636-
1637-
// set the new length, which means the second instance of
1638-
// the last element is forgotten.
1639-
self.set_len(next_len);
1640-
1641-
Some(head)
1642-
}
1643-
}
1644-
}
1628+
self.remove_opt(0)
16451629
}
16461630

16471631
fn unshift(&mut self, x: T) {
1648-
let v = util::replace(self, ~[x]);
1649-
self.push_all_move(v);
1632+
self.insert(0, x)
16501633
}
1651-
fn insert(&mut self, i: uint, x:T) {
1634+
1635+
fn insert(&mut self, i: uint, x: T) {
16521636
let len = self.len();
16531637
assert!(i <= len);
1654-
1655-
self.push(x);
1656-
let mut j = len;
1657-
while j > i {
1658-
self.swap(j, j - 1);
1659-
j -= 1;
1638+
// space for the new element
1639+
self.reserve_additional(1);
1640+
1641+
unsafe { // infallible
1642+
// The spot to put the new value
1643+
let p = self.as_mut_ptr().offset(i as int);
1644+
// Shift everything over to make space. (Duplicating the
1645+
// `i`th element into two consecutive places.)
1646+
ptr::copy_memory(p.offset(1), p, len - i);
1647+
// Write it in, overwriting the first copy of the `i`th
1648+
// element.
1649+
intrinsics::move_val_init(&mut *p, x);
1650+
self.set_len(len + 1);
16601651
}
16611652
}
1653+
1654+
#[inline]
16621655
fn remove(&mut self, i: uint) -> T {
1656+
match self.remove_opt(i) {
1657+
Some(t) => t,
1658+
None => fail!("remove: the len is {} but the index is {}", self.len(), i)
1659+
}
1660+
}
1661+
1662+
fn remove_opt(&mut self, i: uint) -> Option<T> {
16631663
let len = self.len();
1664-
assert!(i < len);
1664+
if i < len {
1665+
unsafe { // infallible
1666+
// the place we are taking from.
1667+
let ptr = self.as_mut_ptr().offset(i as int);
1668+
// copy it out, unsafely having a copy of the value on
1669+
// the stack and in the vector at the same time.
1670+
let ret = Some(ptr::read_ptr(ptr as *T));
1671+
1672+
// Shift everything down to fill in that spot.
1673+
ptr::copy_memory(ptr, ptr.offset(1), len - i - 1);
1674+
self.set_len(len - 1);
16651675

1666-
let mut j = i;
1667-
while j < len - 1 {
1668-
self.swap(j, j + 1);
1669-
j += 1;
1676+
ret
1677+
}
1678+
} else {
1679+
None
16701680
}
1671-
self.pop()
16721681
}
16731682
fn swap_remove(&mut self, index: uint) -> T {
16741683
let ln = self.len();
@@ -3380,6 +3389,29 @@ mod tests {
33803389
a.insert(4, 5);
33813390
}
33823391

3392+
#[test]
3393+
fn test_remove_opt() {
3394+
let mut a = ~[1,2,3,4];
3395+
3396+
assert_eq!(a.remove_opt(2), Some(3));
3397+
assert_eq!(a, ~[1,2,4]);
3398+
3399+
assert_eq!(a.remove_opt(2), Some(4));
3400+
assert_eq!(a, ~[1,2]);
3401+
3402+
assert_eq!(a.remove_opt(2), None);
3403+
assert_eq!(a, ~[1,2]);
3404+
3405+
assert_eq!(a.remove_opt(0), Some(1));
3406+
assert_eq!(a, ~[2]);
3407+
3408+
assert_eq!(a.remove_opt(0), Some(2));
3409+
assert_eq!(a, ~[]);
3410+
3411+
assert_eq!(a.remove_opt(0), None);
3412+
assert_eq!(a.remove_opt(10), None);
3413+
}
3414+
33833415
#[test]
33843416
fn test_remove() {
33853417
let mut a = ~[1, 2, 3, 4];
@@ -4092,6 +4124,7 @@ mod bench {
40924124
use vec::VectorVector;
40934125
use option::*;
40944126
use ptr;
4127+
use rand::{weak_rng, Rng};
40954128

40964129
#[bench]
40974130
fn iterator(bh: &mut BenchHarness) {
@@ -4268,4 +4301,28 @@ mod bench {
42684301
}
42694302
});
42704303
}
4304+
4305+
#[bench]
4306+
fn random_inserts(bh: &mut BenchHarness) {
4307+
let mut rng = weak_rng();
4308+
bh.iter(|| {
4309+
let mut v = vec::from_elem(30, (0u, 0u));
4310+
for _ in range(0, 100) {
4311+
let l = v.len();
4312+
v.insert(rng.gen::<uint>() % (l + 1),
4313+
(1, 1));
4314+
}
4315+
})
4316+
}
4317+
#[bench]
4318+
fn random_removes(bh: &mut BenchHarness) {
4319+
let mut rng = weak_rng();
4320+
bh.iter(|| {
4321+
let mut v = vec::from_elem(130, (0u, 0u));
4322+
for _ in range(0, 100) {
4323+
let l = v.len();
4324+
v.remove(rng.gen::<uint>() % l);
4325+
}
4326+
})
4327+
}
42714328
}

0 commit comments

Comments
 (0)