Skip to content

Commit

Permalink
Rollup merge of rust-lang#52859 - ljedrz:smallvec_true_extend, r=Mark…
Browse files Browse the repository at this point in the history
…-Simulacrum

Use Vec::extend in SmallVec::extend when applicable

As calculated in rust-lang#52738, `Vec::extend` is much faster than `push`ing to it in a loop. We can take advantage of this method in `SmallVec` too - at least in cases when its underlying object is an `AccumulateVec::Heap`.

~~This approach also accidentally improves the `push` loop of the `AccumulateVec::Array` variant, because it doesn't utilize `SmallVec::push` which performs `self.reserve(1)` with every iteration; this is unnecessary, because we're already reserving the whole space we will be needing by performing `self.reserve(iter.size_hint().0)` at the beginning.~~
  • Loading branch information
Mark-Simulacrum committed Aug 1, 2018
2 parents fe0c255 + ca52648 commit df2055f
Showing 1 changed file with 128 additions and 4 deletions.
132 changes: 128 additions & 4 deletions src/librustc_data_structures/small_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,18 @@ impl<A: Array> FromIterator<A::Element> for SmallVec<A> {

impl<A: Array> Extend<A::Element> for SmallVec<A> {
fn extend<I: IntoIterator<Item=A::Element>>(&mut self, iter: I) {
let iter = iter.into_iter();
self.reserve(iter.size_hint().0);
for el in iter {
self.push(el);
if self.is_array() {
let iter = iter.into_iter();
self.reserve(iter.size_hint().0);

for el in iter {
self.push(el);
}
} else {
match self.0 {
AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
_ => unreachable!()
}
}
}
}
Expand Down Expand Up @@ -213,3 +221,119 @@ impl<A> Decodable for SmallVec<A>
})
}
}

#[cfg(test)]
mod tests {
extern crate test;
use self::test::Bencher;

use super::*;

#[bench]
fn fill_small_vec_1_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(10);

sv.extend(0..10);
})
}

#[bench]
fn fill_small_vec_1_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::new();

sv.extend(0..10);
})
}

#[bench]
fn fill_small_vec_8_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(10);

sv.extend(0..10);
})
}

#[bench]
fn fill_small_vec_8_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::new();

sv.extend(0..10);
})
}

#[bench]
fn fill_small_vec_32_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(10);

sv.extend(0..10);
})
}

#[bench]
fn fill_small_vec_32_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::new();

sv.extend(0..10);
})
}

#[bench]
fn fill_small_vec_1_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(50);

sv.extend(0..50);
})
}

#[bench]
fn fill_small_vec_1_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::new();

sv.extend(0..50);
})
}

#[bench]
fn fill_small_vec_8_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(50);

sv.extend(0..50);
})
}

#[bench]
fn fill_small_vec_8_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::new();

sv.extend(0..50);
})
}

#[bench]
fn fill_small_vec_32_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(50);

sv.extend(0..50);
})
}

#[bench]
fn fill_small_vec_32_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::new();

sv.extend(0..50);
})
}
}

0 comments on commit df2055f

Please sign in to comment.