From 2b3a37bd2e35458b4d66f13c4d3ad924455ac2bb Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sun, 13 Nov 2016 00:11:16 +0100 Subject: [PATCH 1/2] Restore Vec::from_iter() specialization Since I said "no intentional functional change" in the previous commit, I guess it was inevitable there were unintentional changes. Not functional, but optimization-wise. This restores the extend specialization's use in Vec::from_iter. --- src/libcollections/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 53b7ae0703bf4..5477a1f6331b0 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1517,7 +1517,7 @@ impl FromIterator for Vec { vector } }; - vector.extend_desugared(iterator); + vector.extend(iterator); vector } } From c36edc726156c7868c6845c0e39b5231e35bc1ff Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sun, 13 Nov 2016 01:09:27 +0100 Subject: [PATCH 2/2] vec: Use less code bloat specialized Vec::from_iter Vec::from_iter's general case allocates the vector up front; this is redundant for the TrustedLen case, and can then be avoided to reduce the size of the code. --- src/libcollections/vec.rs | 51 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 5477a1f6331b0..24f8e3a2d9181 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1499,26 +1499,7 @@ impl ops::DerefMut for Vec { impl FromIterator for Vec { #[inline] fn from_iter>(iter: I) -> Vec { - // Unroll the first iteration, as the vector is going to be - // expanded on this iteration in every case when the iterable is not - // empty, but the loop in extend_desugared() is not going to see the - // vector being full in the few subsequent loop iterations. - // So we get better branch prediction. - let mut iterator = iter.into_iter(); - let mut vector = match iterator.next() { - None => return Vec::new(), - Some(element) => { - let (lower, _) = iterator.size_hint(); - let mut vector = Vec::with_capacity(lower.saturating_add(1)); - unsafe { - ptr::write(vector.get_unchecked_mut(0), element); - vector.set_len(1); - } - vector - } - }; - vector.extend(iterator); - vector + >::from_iter(iter.into_iter()) } } @@ -1590,13 +1571,37 @@ impl Extend for Vec { } } +// Specialization trait used for Vec::from_iter and Vec::extend trait SpecExtend { + fn from_iter(iter: I) -> Self; fn spec_extend(&mut self, iter: I); } impl SpecExtend for Vec where I: Iterator, { + default fn from_iter(mut iterator: I) -> Self { + // Unroll the first iteration, as the vector is going to be + // expanded on this iteration in every case when the iterable is not + // empty, but the loop in extend_desugared() is not going to see the + // vector being full in the few subsequent loop iterations. + // So we get better branch prediction. + let mut vector = match iterator.next() { + None => return Vec::new(), + Some(element) => { + let (lower, _) = iterator.size_hint(); + let mut vector = Vec::with_capacity(lower.saturating_add(1)); + unsafe { + ptr::write(vector.get_unchecked_mut(0), element); + vector.set_len(1); + } + vector + } + }; + vector.spec_extend(iterator); + vector + } + default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter) } @@ -1605,6 +1610,12 @@ impl SpecExtend for Vec impl SpecExtend for Vec where I: TrustedLen, { + fn from_iter(iterator: I) -> Self { + let mut vector = Vec::new(); + vector.spec_extend(iterator); + vector + } + fn spec_extend(&mut self, iterator: I) { // This is the case for a TrustedLen iterator. let (low, high) = iterator.size_hint();