Skip to content

Commit ef7ab56

Browse files
authored
Merge pull request #112 from bluss/extend-improvement
Improve .extend() performance (?)
2 parents fa95a80 + fd98c66 commit ef7ab56

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

benches/extend.rs

+30-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
extern crate arrayvec;
33
#[macro_use] extern crate bencher;
44

5+
use std::io::Write;
6+
57
use arrayvec::ArrayVec;
68

79
use bencher::Bencher;
@@ -12,8 +14,9 @@ fn extend_with_constant(b: &mut Bencher) {
1214
let cap = v.capacity();
1315
b.iter(|| {
1416
v.clear();
15-
v.extend((0..cap).map(|_| 1));
16-
v[0]
17+
let constant = black_box(1);
18+
v.extend((0..cap).map(move |_| constant));
19+
v[511]
1720
});
1821
b.bytes = v.capacity() as u64;
1922
}
@@ -23,8 +26,9 @@ fn extend_with_range(b: &mut Bencher) {
2326
let cap = v.capacity();
2427
b.iter(|| {
2528
v.clear();
26-
v.extend((0..cap).map(|x| x as _));
27-
v[0]
29+
let range = 0..cap;
30+
v.extend(range.map(|x| black_box(x as _)));
31+
v[511]
2832
});
2933
b.bytes = v.capacity() as u64;
3034
}
@@ -34,8 +38,20 @@ fn extend_with_slice(b: &mut Bencher) {
3438
let data = [1; 512];
3539
b.iter(|| {
3640
v.clear();
37-
v.extend(black_box(data.iter()).cloned());
38-
v[0]
41+
let iter = data.iter().map(|&x| x);
42+
v.extend(iter);
43+
v[511]
44+
});
45+
b.bytes = v.capacity() as u64;
46+
}
47+
48+
fn extend_with_write(b: &mut Bencher) {
49+
let mut v = ArrayVec::<[u8; 512]>::new();
50+
let data = [1; 512];
51+
b.iter(|| {
52+
v.clear();
53+
v.write(&data[..]).ok();
54+
v[511]
3955
});
4056
b.bytes = v.capacity() as u64;
4157
}
@@ -51,5 +67,12 @@ fn extend_from_slice(b: &mut Bencher) {
5167
b.bytes = v.capacity() as u64;
5268
}
5369

54-
benchmark_group!(benches, extend_with_constant, extend_with_range, extend_with_slice, extend_from_slice);
70+
benchmark_group!(benches,
71+
extend_with_constant,
72+
extend_with_range,
73+
extend_with_slice,
74+
extend_with_write,
75+
extend_from_slice
76+
);
77+
5578
benchmark_main!(benches);

src/lib.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,7 @@ impl<A: Array> Extend<A::Item> for ArrayVec<A> {
933933
unsafe {
934934
let len = self.len();
935935
let mut ptr = self.as_mut_ptr().offset(len as isize);
936+
let end_ptr = ptr.offset(take as isize);
936937
// Keep the length in a separate variable, write it back on scope
937938
// exit. To help the compiler with alias analysis and stuff.
938939
// We update the length to handle panic in the iteration of the
@@ -944,10 +945,16 @@ impl<A: Array> Extend<A::Item> for ArrayVec<A> {
944945
**self_len = Index::from(len);
945946
}
946947
};
947-
for elt in iter.into_iter().take(take) {
948-
ptr::write(ptr, elt);
949-
ptr = ptr.offset(1);
950-
guard.data += 1;
948+
let mut iter = iter.into_iter();
949+
loop {
950+
if ptr == end_ptr { break; }
951+
if let Some(elt) = iter.next() {
952+
ptr::write(ptr, elt);
953+
ptr = ptr.offset(1);
954+
guard.data += 1;
955+
} else {
956+
break;
957+
}
951958
}
952959
}
953960
}

0 commit comments

Comments
 (0)