Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Aug 1, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably we should match on self here and either extend or push based on that, but maybe it's not worth it. Benchmarks would be good, but that's quite a bit of work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean instead of is_array? I wanted to do that, but I ran into issues with the borrow checker. I'm going to think about some possible benchmarks.

self.push(el);
}
} else {
match self.0 {
AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
_ => unreachable!()
}
}
}
}
Expand Down Expand Up @@ -217,3 +225,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);
})
}
}