From e9946f99b97fa1efda39b657448aae0238b66220 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Wed, 23 Sep 2015 08:49:50 -0400 Subject: [PATCH 1/2] Override `clone_from` for `{BinaryHeap, String}` CC #28481 --- src/libcollections/binary_heap.rs | 12 +++++++++++- src/libcollections/string.rs | 13 ++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index a3e32b59b710d..b7afe9685778e 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -167,12 +167,22 @@ use vec::{self, Vec}; /// item's ordering relative to any other item, as determined by the `Ord` /// trait, changes while it is in the heap. This is normally only possible /// through `Cell`, `RefCell`, global state, I/O, or unsafe code. -#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BinaryHeap { data: Vec, } +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BinaryHeap { + fn clone(&self) -> Self { + BinaryHeap { data: self.data.clone() } + } + + fn clone_from(&mut self, source: &Self) { + self.data.clone_from(&source.data); + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Default for BinaryHeap { #[inline] diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index bb65d7469ab14..ba921fed68b1d 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -30,7 +30,7 @@ use vec::Vec; use boxed::Box; /// A growable string stored as a UTF-8 encoded buffer. -#[derive(Clone, PartialOrd, Eq, Ord)] +#[derive(PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct String { vec: Vec, @@ -765,6 +765,17 @@ impl fmt::Display for FromUtf16Error { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for String { + fn clone(&self) -> Self { + String { vec: self.vec.clone() } + } + + fn clone_from(&mut self, source: &Self) { + self.vec.clone_from(&source.vec); + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for String { fn from_iter>(iterable: I) -> String { From 97f2a325644eb88b50fb5b52e09933535fa29c40 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Wed, 23 Sep 2015 10:33:36 -0400 Subject: [PATCH 2/2] Optimize `Vec::clone_from` Before: test dst_bigger::src_100_dst_1000::clone ... bench: 34 ns/iter (+/- 1) test dst_bigger::src_100_dst_1000::clone_from ... bench: 75 ns/iter (+/- 3) test dst_bigger::src_10_dst_100::clone ... bench: 25 ns/iter (+/- 0) test dst_bigger::src_10_dst_100::clone_from ... bench: 9 ns/iter (+/- 1) test eq::src_1000_dst_1000::clone ... bench: 105 ns/iter (+/- 2) test eq::src_1000_dst_1000::clone_from ... bench: 593 ns/iter (+/- 21) test eq::src_100_dst_100::clone ... bench: 34 ns/iter (+/- 1) test eq::src_100_dst_100::clone_from ... bench: 75 ns/iter (+/- 1) test src_bigger::src_1000_dst_100::clone ... bench: 103 ns/iter (+/- 5) test src_bigger::src_1000_dst_100::clone_from ... bench: 148 ns/iter (+/- 5) test src_bigger::src_100_dst_10::clone ... bench: 34 ns/iter (+/- 1) test src_bigger::src_100_dst_10::clone_from ... bench: 20 ns/iter (+/- 0) After: test dst_bigger::src_100_dst_1000::clone ... bench: 34 ns/iter (+/- 2) test dst_bigger::src_100_dst_1000::clone_from ... bench: 15 ns/iter (+/- 1) test dst_bigger::src_10_dst_100::clone ... bench: 26 ns/iter (+/- 1) test dst_bigger::src_10_dst_100::clone_from ... bench: 7 ns/iter (+/- 0) test eq::src_1000_dst_1000::clone ... bench: 103 ns/iter (+/- 1) test eq::src_1000_dst_1000::clone_from ... bench: 85 ns/iter (+/- 4) test eq::src_100_dst_100::clone ... bench: 34 ns/iter (+/- 2) test eq::src_100_dst_100::clone_from ... bench: 15 ns/iter (+/- 1) test src_bigger::src_1000_dst_100::clone ... bench: 103 ns/iter (+/- 4) test src_bigger::src_1000_dst_100::clone_from ... bench: 90 ns/iter (+/- 2) test src_bigger::src_100_dst_10::clone ... bench: 34 ns/iter (+/- 2) test src_bigger::src_100_dst_10::clone_from ... bench: 20 ns/iter (+/- 0) Closes #28601. --- src/libcollections/lib.rs | 2 +- src/libcollections/vec.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 34bd1345fcb3b..03ee8ba31b1d2 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -62,7 +62,7 @@ #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(decode_utf16)] #![feature(utf8_error)] -#![cfg_attr(test, feature(rand, test))] +#![cfg_attr(test, feature(clone_from_slice, rand, test))] #![feature(no_std)] #![no_std] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 4110faa41b324..de3e6f94e8746 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1007,19 +1007,15 @@ impl Clone for Vec { fn clone_from(&mut self, other: &Vec) { // drop anything in self that will not be overwritten - if self.len() > other.len() { - self.truncate(other.len()) - } + self.truncate(other.len()); + let len = self.len(); // reuse the contained values' allocations/resources. - for (place, thing) in self.iter_mut().zip(other) { - place.clone_from(thing) - } + self.clone_from_slice(&other[..len]); // self.len <= other.len due to the truncate above, so the // slice here is always in-bounds. - let slice = &other[self.len()..]; - self.push_all(slice); + self.push_all(&other[len..]); } }