Optimize unnecessary check in VecDeque::retain

Signed-off-by: Xuanwo <github@xuanwo.io>
This commit is contained in:
Xuanwo 2021-08-16 13:37:51 +08:00
parent 2bd17c1d43
commit b4b495e48e
No known key found for this signature in database
GPG key ID: 4B9C95AE0483322D
2 changed files with 59 additions and 8 deletions

View file

@ -2129,16 +2129,32 @@ impl<T, A: Allocator> VecDeque<T, A> {
F: FnMut(&T) -> bool,
{
let len = self.len();
let mut del = 0;
for i in 0..len {
if !f(&self[i]) {
del += 1;
} else if del > 0 {
self.swap(i - del, i);
let mut idx = 0;
let mut cur = 0;
// Stage 1: All values are retained.
while cur < len {
if !f(&self[cur]) {
cur += 1;
break;
}
cur += 1;
idx += 1;
}
if del > 0 {
self.truncate(len - del);
// Stage 2: Swap retained value into current idx.
while cur < len {
if !f(&self[cur]) {
cur += 1;
continue;
}
self.swap(idx, cur);
cur += 1;
idx += 1;
}
// Stage 3: Trancate all values after idx.
if cur != idx {
self.truncate(idx);
}
}

View file

@ -40,6 +40,39 @@ fn bench_pop_back_100(b: &mut test::Bencher) {
})
}
#[bench]
#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
fn bench_retain_whole_10000(b: &mut test::Bencher) {
let v = (1..100000).collect::<VecDeque<u32>>();
b.iter(|| {
let mut v = v.clone();
v.retain(|x| *x > 0)
})
}
#[bench]
#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
fn bench_retain_odd_10000(b: &mut test::Bencher) {
let v = (1..100000).collect::<VecDeque<u32>>();
b.iter(|| {
let mut v = v.clone();
v.retain(|x| x & 1 == 0)
})
}
#[bench]
#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
fn bench_retain_half_10000(b: &mut test::Bencher) {
let v = (1..100000).collect::<VecDeque<u32>>();
b.iter(|| {
let mut v = v.clone();
v.retain(|x| *x > 50000)
})
}
#[bench]
#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks
fn bench_pop_front_100(b: &mut test::Bencher) {
@ -54,6 +87,8 @@ fn bench_pop_front_100(b: &mut test::Bencher) {
})
}
#[test]
fn test_swap_front_back_remove() {
fn test(back: bool) {