Skip to content

Commit 855f85c

Browse files
author
bors-servo
authored
Auto merge of #29 - nipunn1313:extend_slice, r=jdm
Implement extend_from_slice and insert_from_slice with memmove optimization Implement the performance optimized versions of insert_many and extend (from #28). These methods use memmove rather than a looped insert. If we had function specialization, we could implement these without exposing new methods. Up to the maintainers whether we want to support these new methods. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/29) <!-- Reviewable:end -->
2 parents 03c016c + aef2113 commit 855f85c

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

benches/bench.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,27 @@ fn bench_extend(b: &mut Bencher) {
6363
});
6464
}
6565

66+
#[bench]
67+
fn bench_extend_from_slice(b: &mut Bencher) {
68+
let v: Vec<u64> = (0..100).collect();
69+
b.iter(|| {
70+
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
71+
vec.extend_from_slice(&v);
72+
vec
73+
});
74+
}
75+
76+
#[bench]
77+
fn bench_insert_from_slice(b: &mut Bencher) {
78+
let v: Vec<u64> = (0..100).collect();
79+
b.iter(|| {
80+
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
81+
vec.insert_from_slice(0, &v);
82+
vec.insert_from_slice(0, &v);
83+
vec
84+
});
85+
}
86+
6687
#[bench]
6788
fn bench_pushpop(b: &mut Bencher) {
6889
#[inline(never)]

lib.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,29 @@ impl<A: Array> SmallVec<A> {
477477
}
478478
}
479479

480+
impl<A: Array> SmallVec<A> where A::Item: Copy {
481+
pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) {
482+
self.reserve(slice.len());
483+
484+
let len = self.len;
485+
assert!(index <= len);
486+
487+
unsafe {
488+
let slice_ptr = slice.as_ptr();
489+
let ptr = self.as_mut_ptr().offset(index as isize);
490+
ptr::copy(ptr, ptr.offset(slice.len() as isize), len - index);
491+
ptr::copy(slice_ptr, ptr, slice.len());
492+
self.set_len(len + slice.len());
493+
}
494+
}
495+
496+
#[inline]
497+
pub fn extend_from_slice(&mut self, slice: &[A::Item]) {
498+
let len = self.len();
499+
self.insert_from_slice(len, slice);
500+
}
501+
}
502+
480503
impl<A: Array> ops::Deref for SmallVec<A> {
481504
type Target = [A::Item];
482505
#[inline]
@@ -1068,6 +1091,28 @@ pub mod tests {
10681091
v.grow(5);
10691092
}
10701093

1094+
#[test]
1095+
fn test_insert_from_slice() {
1096+
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
1097+
for x in 0..4 {
1098+
v.push(x);
1099+
}
1100+
assert_eq!(v.len(), 4);
1101+
v.insert_from_slice(1, &[5, 6]);
1102+
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
1103+
}
1104+
1105+
#[test]
1106+
fn test_extend_from_slice() {
1107+
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
1108+
for x in 0..4 {
1109+
v.push(x);
1110+
}
1111+
assert_eq!(v.len(), 4);
1112+
v.extend_from_slice(&[5, 6]);
1113+
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 1, 2, 3, 5, 6]);
1114+
}
1115+
10711116
#[test]
10721117
#[should_panic]
10731118
fn test_drop_panic_smallvec() {

0 commit comments

Comments
 (0)