Skip to content

Commit dc6c0ac

Browse files
author
bors-servo
authored
Auto merge of #118 - llogiq:optimize-from-slice, r=mbrubeck
bench and optimize `from_slice` This adds "bench_from_slice(_vec)(_small)" benches, renaming the previous versions to "bench_from_iter*" (because they were using `From<&[T]>`, which calls `FromIterator` internally) and optimizes the `from_slice` constructor considerably. Before: ``` test bench_from_slice ... bench: 42 ns/iter (+/- 0) test bench_from_slice_small ... bench: 12 ns/iter (+/- 0) ``` After: ``` test bench_from_slice ... bench: 27 ns/iter (+/- 0) test bench_from_slice_small ... bench: 8 ns/iter (+/- 0) ``` <!-- 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/118) <!-- Reviewable:end -->
2 parents 52e7c01 + 7633aeb commit dc6c0ac

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

benches/bench.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ trait Vector<T>: for<'a> From<&'a [T]> + Extend<T> + ExtendFromSlice<T> {
1717
fn remove(&mut self, p: usize) -> T;
1818
fn insert(&mut self, n: usize, val: T);
1919
fn from_elem(val: T, n: usize) -> Self;
20+
fn from_elems(val: &[T]) -> Self;
2021
}
2122

2223
impl<T: Copy> Vector<T> for Vec<T> {
@@ -43,6 +44,10 @@ impl<T: Copy> Vector<T> for Vec<T> {
4344
fn from_elem(val: T, n: usize) -> Self {
4445
vec![val; n]
4546
}
47+
48+
fn from_elems(val: &[T]) -> Self {
49+
val.to_owned()
50+
}
4651
}
4752

4853
impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> {
@@ -69,6 +74,10 @@ impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> {
6974
fn from_elem(val: T, n: usize) -> Self {
7075
smallvec![val; n]
7176
}
77+
78+
fn from_elems(val: &[T]) -> Self {
79+
SmallVec::from_slice(val)
80+
}
7281
}
7382

7483
macro_rules! make_benches {
@@ -92,6 +101,8 @@ make_benches! {
92101
bench_remove_small => gen_remove(VEC_SIZE as _),
93102
bench_extend => gen_extend(SPILLED_SIZE as _),
94103
bench_extend_small => gen_extend(VEC_SIZE as _),
104+
bench_from_iter => gen_from_iter(SPILLED_SIZE as _),
105+
bench_from_iter_small => gen_from_iter(VEC_SIZE as _),
95106
bench_from_slice => gen_from_slice(SPILLED_SIZE as _),
96107
bench_from_slice_small => gen_from_slice(VEC_SIZE as _),
97108
bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _),
@@ -112,6 +123,8 @@ make_benches! {
112123
bench_remove_vec_small => gen_remove(VEC_SIZE as _),
113124
bench_extend_vec => gen_extend(SPILLED_SIZE as _),
114125
bench_extend_vec_small => gen_extend(VEC_SIZE as _),
126+
bench_from_iter_vec => gen_from_iter(SPILLED_SIZE as _),
127+
bench_from_iter_vec_small => gen_from_iter(VEC_SIZE as _),
115128
bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _),
116129
bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _),
117130
bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _),
@@ -179,14 +192,22 @@ fn gen_extend<V: Vector<u64>>(n: u64, b: &mut Bencher) {
179192
});
180193
}
181194

182-
fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
195+
fn gen_from_iter<V: Vector<u64>>(n: u64, b: &mut Bencher) {
183196
let v: Vec<u64> = (0..n).collect();
184197
b.iter(|| {
185198
let vec = V::from(&v);
186199
vec
187200
});
188201
}
189202

203+
fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
204+
let v: Vec<u64> = (0..n).collect();
205+
b.iter(|| {
206+
let vec = V::from_elems(&v);
207+
vec
208+
});
209+
}
210+
190211
fn gen_extend_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) {
191212
let v: Vec<u64> = (0..n).collect();
192213
b.iter(|| {

lib.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -946,9 +946,25 @@ impl<A: Array> SmallVec<A> where A::Item: Copy {
946946
///
947947
/// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`.
948948
pub fn from_slice(slice: &[A::Item]) -> Self {
949-
let mut vec = Self::new();
950-
vec.extend_from_slice(slice);
951-
vec
949+
let len = slice.len();
950+
if len <= A::size() {
951+
SmallVec {
952+
capacity: len,
953+
data: SmallVecData::from_inline(unsafe {
954+
let mut data: A = mem::uninitialized();
955+
ptr::copy_nonoverlapping(slice.as_ptr(), data.ptr_mut(), len);
956+
data
957+
})
958+
}
959+
} else {
960+
let mut b = slice.to_vec();
961+
let ptr = b.as_mut_ptr();
962+
mem::forget(b);
963+
SmallVec {
964+
capacity: len,
965+
data: SmallVecData::from_heap(ptr, len),
966+
}
967+
}
952968
}
953969

954970
/// Copy elements from a slice into the vector at position `index`, shifting any following

0 commit comments

Comments
 (0)