diff --git a/benches/bench.rs b/benches/bench.rs index c439bec..36cb133 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -17,6 +17,7 @@ trait Vector: for<'a> From<&'a [T]> + Extend + ExtendFromSlice { fn remove(&mut self, p: usize) -> T; fn insert(&mut self, n: usize, val: T); fn from_elem(val: T, n: usize) -> Self; + fn from_elems(val: &[T]) -> Self; } impl Vector for Vec { @@ -43,6 +44,10 @@ impl Vector for Vec { fn from_elem(val: T, n: usize) -> Self { vec![val; n] } + + fn from_elems(val: &[T]) -> Self { + val.to_owned() + } } impl Vector for SmallVec<[T; VEC_SIZE]> { @@ -69,6 +74,10 @@ impl Vector for SmallVec<[T; VEC_SIZE]> { fn from_elem(val: T, n: usize) -> Self { smallvec![val; n] } + + fn from_elems(val: &[T]) -> Self { + SmallVec::from_slice(val) + } } macro_rules! make_benches { @@ -92,6 +101,8 @@ make_benches! { bench_remove_small => gen_remove(VEC_SIZE as _), bench_extend => gen_extend(SPILLED_SIZE as _), bench_extend_small => gen_extend(VEC_SIZE as _), + bench_from_iter => gen_from_iter(SPILLED_SIZE as _), + bench_from_iter_small => gen_from_iter(VEC_SIZE as _), bench_from_slice => gen_from_slice(SPILLED_SIZE as _), bench_from_slice_small => gen_from_slice(VEC_SIZE as _), bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _), @@ -112,6 +123,8 @@ make_benches! { bench_remove_vec_small => gen_remove(VEC_SIZE as _), bench_extend_vec => gen_extend(SPILLED_SIZE as _), bench_extend_vec_small => gen_extend(VEC_SIZE as _), + bench_from_iter_vec => gen_from_iter(SPILLED_SIZE as _), + bench_from_iter_vec_small => gen_from_iter(VEC_SIZE as _), bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _), bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _), bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _), @@ -179,7 +192,7 @@ fn gen_extend>(n: u64, b: &mut Bencher) { }); } -fn gen_from_slice>(n: u64, b: &mut Bencher) { +fn gen_from_iter>(n: u64, b: &mut Bencher) { let v: Vec = (0..n).collect(); b.iter(|| { let vec = V::from(&v); @@ -187,6 +200,14 @@ fn gen_from_slice>(n: u64, b: &mut Bencher) { }); } +fn gen_from_slice>(n: u64, b: &mut Bencher) { + let v: Vec = (0..n).collect(); + b.iter(|| { + let vec = V::from_elems(&v); + vec + }); +} + fn gen_extend_from_slice>(n: u64, b: &mut Bencher) { let v: Vec = (0..n).collect(); b.iter(|| { diff --git a/lib.rs b/lib.rs index e132f44..881021e 100644 --- a/lib.rs +++ b/lib.rs @@ -946,9 +946,25 @@ impl SmallVec where A::Item: Copy { /// /// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`. pub fn from_slice(slice: &[A::Item]) -> Self { - let mut vec = Self::new(); - vec.extend_from_slice(slice); - vec + let len = slice.len(); + if len <= A::size() { + SmallVec { + capacity: len, + data: SmallVecData::from_inline(unsafe { + let mut data: A = mem::uninitialized(); + ptr::copy_nonoverlapping(slice.as_ptr(), data.ptr_mut(), len); + data + }) + } + } else { + let mut b = slice.to_vec(); + let ptr = b.as_mut_ptr(); + mem::forget(b); + SmallVec { + capacity: len, + data: SmallVecData::from_heap(ptr, len), + } + } } /// Copy elements from a slice into the vector at position `index`, shifting any following