From 5444f601dc02cd9f5fc886f438ea60310f664cc6 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 28 Sep 2013 04:53:20 +0200 Subject: [PATCH 1/3] std::vec: Add benchmark for .concat_vec and .connect_vec --- src/libstd/vec.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index be5ab35ff88..ef4f508282c 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -3758,7 +3758,9 @@ mod tests { #[cfg(test)] mod bench { use extra::test::BenchHarness; + use iter::range; use vec; + use vec::VectorVector; use option::*; #[bench] @@ -3798,4 +3800,20 @@ mod bench { xs + ys; } } + + #[bench] + fn concat(bh: &mut BenchHarness) { + let xss: &[~[uint]] = vec::from_fn(100, |i| range(0, i).collect()); + do bh.iter { + xss.concat_vec(); + } + } + + #[bench] + fn connect(bh: &mut BenchHarness) { + let xss: &[~[uint]] = vec::from_fn(100, |i| range(0, i).collect()); + do bh.iter { + xss.connect_vec(&0); + } + } } From 24a4d0daf0ba954b94eeeb9eb83355cd2f16ede5 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 28 Sep 2013 04:15:40 +0200 Subject: [PATCH 2/3] std::vec: Sane implementations for connect_vec and concat_vec Avoid unnecessary copying of subvectors, and calculate the needed space beforehand. These implementations are simple but better than the previous. Also only implement it once, for all `Vector` using: impl<'self, T: Clone, V: Vector> VectorVector for &'self [V] performance improved according to the bench test: before test vec::bench::concat ... bench: 74818 ns/iter (+/- 408) test vec::bench::connect ... bench: 87066 ns/iter (+/- 376) after test vec::bench::concat ... bench: 17724 ns/iter (+/- 126) test vec::bench::connect ... bench: 18353 ns/iter (+/- 691) Closes #9581 --- src/libstd/vec.rs | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index ef4f508282c..4d7d4bffdf1 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -356,43 +356,32 @@ pub fn connect_slices(v: &[&[T]], sep: &T) -> ~[T] { v.connect_vec(sep) pub trait VectorVector { // FIXME #5898: calling these .concat and .connect conflicts with // StrVector::con{cat,nect}, since they have generic contents. + /// Flattens a vector of vectors of T into a single vector of T. fn concat_vec(&self) -> ~[T]; + + /// Concatenate a vector of vectors, placing a given separator between each. fn connect_vec(&self, sep: &T) -> ~[T]; } -impl<'self, T:Clone> VectorVector for &'self [~[T]] { - /// Flattens a vector of slices of T into a single vector of T. +impl<'self, T: Clone, V: Vector> VectorVector for &'self [V] { fn concat_vec(&self) -> ~[T] { - self.flat_map(|inner| (*inner).clone()) - } - - /// Concatenate a vector of vectors, placing a given separator between each. - fn connect_vec(&self, sep: &T) -> ~[T] { - let mut r = ~[]; - let mut first = true; - for inner in self.iter() { - if first { first = false; } else { r.push((*sep).clone()); } - r.push_all((*inner).clone()); + let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len()); + let mut result = with_capacity(size); + for v in self.iter() { + result.push_all(v.as_slice()) } - r - } -} - -impl<'self,T:Clone> VectorVector for &'self [&'self [T]] { - /// Flattens a vector of slices of T into a single vector of T. - fn concat_vec(&self) -> ~[T] { - self.flat_map(|&inner| inner.to_owned()) + result } - /// Concatenate a vector of slices, placing a given separator between each. fn connect_vec(&self, sep: &T) -> ~[T] { - let mut r = ~[]; + let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len()); + let mut result = with_capacity(size + self.len()); let mut first = true; - for &inner in self.iter() { - if first { first = false; } else { r.push((*sep).clone()); } - r.push_all(inner); + for v in self.iter() { + if first { first = false } else { result.push(sep.clone()) } + result.push_all(v.as_slice()) } - r + result } } From 3709aa78d8fc75ed739e837d7c96205b8494188d Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 28 Sep 2013 04:37:20 +0200 Subject: [PATCH 3/3] std::vec: Remove functions concat, connect std::vec::{concat, connect, concat_slices, connect_slices} are replaced by the already existing trait methods .concat_vec() and .connect_vec(). --- src/librustc/middle/check_match.rs | 4 ++-- src/librustdoc/clean.rs | 11 +++++------ src/libstd/vec.rs | 25 +++++-------------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 8fc98ac10c7..c9eded645fa 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -773,12 +773,12 @@ pub fn specialize(cx: &MatchCheckCtxt, let num_elements = before.len() + after.len(); if num_elements < arity && slice.is_some() { Some(vec::append( - vec::concat(&[ + [ before, vec::from_elem( arity - num_elements, wild()), after - ]), + ].concat_vec(), r.tail() )) } else if num_elements == arity { diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index 623ac82486d..70f1815b462 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -173,12 +173,11 @@ impl Clean for doctree::Module { visibility: self.vis.clean(), id: self.id, inner: ModuleItem(Module { - items: std::vec::concat(&[self.structs.clean(), - self.enums.clean(), self.fns.clean(), - std::vec::concat(self.foreigns.clean()), - self.mods.clean(), self.typedefs.clean(), - self.statics.clean(), self.traits.clean(), - self.impls.clean(), self.view_items.clean()]) + items: [self.structs.clean(), self.enums.clean(), + self.fns.clean(), self.foreigns.clean().concat_vec(), + self.mods.clean(), self.typedefs.clean(), + self.statics.clean(), self.traits.clean(), + self.impls.clean(), self.view_items.clean()].concat_vec() }) } } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 4d7d4bffdf1..1398f08bb7c 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -340,18 +340,6 @@ pub fn flat_map(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] { result } -/// Flattens a vector of vectors of T into a single vector of T. -pub fn concat(v: &[~[T]]) -> ~[T] { v.concat_vec() } - -/// Concatenate a vector of vectors, placing a given separator between each -pub fn connect(v: &[~[T]], sep: &T) -> ~[T] { v.connect_vec(sep) } - -/// Flattens a vector of vectors of T into a single vector of T. -pub fn concat_slices(v: &[&[T]]) -> ~[T] { v.concat_vec() } - -/// Concatenate a vector of vectors, placing a given separator between each -pub fn connect_slices(v: &[&[T]], sep: &T) -> ~[T] { v.connect_vec(sep) } - #[allow(missing_doc)] pub trait VectorVector { // FIXME #5898: calling these .concat and .connect conflicts with @@ -3098,24 +3086,21 @@ mod tests { #[test] fn test_concat() { - assert_eq!(concat([~[1], ~[2,3]]), ~[1, 2, 3]); + let v: [~[int], ..0] = []; + assert_eq!(v.concat_vec(), ~[]); assert_eq!([~[1], ~[2,3]].concat_vec(), ~[1, 2, 3]); - assert_eq!(concat_slices([&[1], &[2,3]]), ~[1, 2, 3]); assert_eq!([&[1], &[2,3]].concat_vec(), ~[1, 2, 3]); } #[test] fn test_connect() { - assert_eq!(connect([], &0), ~[]); - assert_eq!(connect([~[1], ~[2, 3]], &0), ~[1, 0, 2, 3]); - assert_eq!(connect([~[1], ~[2], ~[3]], &0), ~[1, 0, 2, 0, 3]); + let v: [~[int], ..0] = []; + assert_eq!(v.connect_vec(&0), ~[]); assert_eq!([~[1], ~[2, 3]].connect_vec(&0), ~[1, 0, 2, 3]); assert_eq!([~[1], ~[2], ~[3]].connect_vec(&0), ~[1, 0, 2, 0, 3]); - assert_eq!(connect_slices([], &0), ~[]); - assert_eq!(connect_slices([&[1], &[2, 3]], &0), ~[1, 0, 2, 3]); - assert_eq!(connect_slices([&[1], &[2], &[3]], &0), ~[1, 0, 2, 0, 3]); + assert_eq!(v.connect_vec(&0), ~[]); assert_eq!([&[1], &[2, 3]].connect_vec(&0), ~[1, 0, 2, 3]); assert_eq!([&[1], &[2], &[3]].connect_vec(&0), ~[1, 0, 2, 0, 3]); }