From b4b495e48e8f42c22090dfadfe9b9b51317ccf02 Mon Sep 17 00:00:00 2001 From: Xuanwo Date: Mon, 16 Aug 2021 13:37:51 +0800 Subject: [PATCH 1/2] Optimize unnecessary check in VecDeque::retain Signed-off-by: Xuanwo --- .../alloc/src/collections/vec_deque/mod.rs | 32 ++++++++++++----- .../alloc/src/collections/vec_deque/tests.rs | 35 +++++++++++++++++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 9a2205420a14b..e4b28204158d9 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2129,16 +2129,32 @@ impl VecDeque { 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); } } diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 6116cfe1d0110..bf1c73eb07803 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -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::>(); + + 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::>(); + + 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::>(); + + 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) { From e32f4c06d34ecb4b55b678bbff35d8a77f81cf16 Mon Sep 17 00:00:00 2001 From: Xuanwo Date: Mon, 16 Aug 2021 13:45:18 +0800 Subject: [PATCH 2/2] Remove extra empty lines Signed-off-by: Xuanwo --- library/alloc/src/collections/vec_deque/tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index bf1c73eb07803..56257e4346254 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -87,8 +87,6 @@ fn bench_pop_front_100(b: &mut test::Bencher) { }) } - - #[test] fn test_swap_front_back_remove() { fn test(back: bool) {