From 65fa109f861a0c5a9430411af7cac6a979204af8 Mon Sep 17 00:00:00 2001 From: Jef Date: Mon, 7 May 2018 13:30:55 +0200 Subject: [PATCH 1/3] Optimize `extend` and `from_elem` --- lib.rs | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/lib.rs b/lib.rs index eaa157a..35c1254 100644 --- a/lib.rs +++ b/lib.rs @@ -637,6 +637,10 @@ impl SmallVec { /// back. pub fn insert_many>(&mut self, index: usize, iterable: I) { let iter = iterable.into_iter(); + if index == self.len() { + return self.extend(iter); + } + let (lower_size_bound, _) = iter.size_hint(); assert!(lower_size_bound <= std::isize::MAX as usize); // Ensure offset is indexable assert!(index + lower_size_bound >= index); // Protect against overflow @@ -805,9 +809,23 @@ impl SmallVec where A::Item: Clone { /// assert_eq!(v, SmallVec::from_buf(['d', 'd'])); /// ``` pub fn from_elem(elem: A::Item, n: usize) -> Self { - let mut v = SmallVec::with_capacity(n); - v.insert_many(0, (0..n).map(|_| elem.clone())); - v + if n > A::size() { + ::std::vec::from_elem(elem, n).into() + } else { + unsafe { + let mut arr: A = ::std::mem::uninitialized(); + let ptr = arr.ptr_mut(); + + for i in 0..n as isize { + ::std::ptr::write(ptr.offset(i), elem.clone()); + } + + SmallVec { + data: Inline { array: arr }, + len: n, + } + } + } } } @@ -1001,13 +1019,30 @@ impl FromIterator for SmallVec { impl Extend for SmallVec { fn extend>(&mut self, iterable: I) { - let iter = iterable.into_iter(); + let mut iter = iterable.into_iter(); let (lower_size_bound, _) = iter.size_hint(); let target_len = self.len + lower_size_bound; if target_len > self.capacity() { - self.grow(target_len); + self.grow(target_len); + } + + unsafe { + let ptr = self.as_mut_ptr().offset(self.len() as isize); + + let len = self.len(); + let mut count = 0; + for p in 0..lower_size_bound as isize { + if let Some(out) = iter.next() { + ::std::ptr::write(ptr.offset(p), out); + count += 1; + } else { + break; + } + } + + self.set_len(len + count); } for elem in iter { From edab5b2b7db5910934fad47890f4c6c94c3d25cb Mon Sep 17 00:00:00 2001 From: Jef Date: Mon, 7 May 2018 13:47:26 +0200 Subject: [PATCH 2/3] Use the (stable) macro instead of the function --- lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib.rs b/lib.rs index 35c1254..e9ee68b 100644 --- a/lib.rs +++ b/lib.rs @@ -810,7 +810,7 @@ impl SmallVec where A::Item: Clone { /// ``` pub fn from_elem(elem: A::Item, n: usize) -> Self { if n > A::size() { - ::std::vec::from_elem(elem, n).into() + vec![elem; n].into() } else { unsafe { let mut arr: A = ::std::mem::uninitialized(); From 401fb09a2f7bbdede63ee83935f8fe7d0d48afce Mon Sep 17 00:00:00 2001 From: Jef Date: Mon, 7 May 2018 13:53:16 +0200 Subject: [PATCH 3/3] Import the macro from `alloc` instead of `std` when `std` is unavailable --- lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib.rs b/lib.rs index e9ee68b..05fc4da 100644 --- a/lib.rs +++ b/lib.rs @@ -21,7 +21,7 @@ #[cfg(not(feature = "std"))] -#[cfg_attr(test, macro_use)] +#[macro_use] extern crate alloc; #[cfg(not(feature = "std"))]