From 262452308a3192fecc3f4d88a2690dc67e681ef5 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 4 Oct 2023 16:21:02 +0200 Subject: [PATCH 1/2] add benchmark for generic slice PartialEq impl --- library/core/benches/slice.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/core/benches/slice.rs b/library/core/benches/slice.rs index 3bfb35e684ea1..1ec51653d92ef 100644 --- a/library/core/benches/slice.rs +++ b/library/core/benches/slice.rs @@ -171,3 +171,17 @@ fn fold_to_last(b: &mut Bencher) { let slice: &[i32] = &[0; 1024]; b.iter(|| black_box(slice).iter().fold(None, |_, r| Some(NonNull::from(r)))); } + +#[bench] +fn slice_cmp_generic(b: &mut Bencher) { + #[derive(PartialEq, Clone, Copy)] + struct Foo(u32, u32); + + let left = [Foo(128, 128); 128]; + let right = [Foo(128, 128); 128]; + + b.iter(|| { + let (left, right) = (black_box(&left), black_box(&right)); + left.as_slice() == right.as_slice() + }); +} From 9d3905f88f12308d79e9e4e0142fa44f1e214a75 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Wed, 4 Oct 2023 16:21:21 +0200 Subject: [PATCH 2/2] unroll slice::equal impl --- library/core/src/slice/cmp.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 075347b80d031..e3b80226e9f12 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -60,7 +60,22 @@ where return false; } - self.iter().zip(other.iter()).all(|(x, y)| x == y) + let (chunks_a, residual_a) = self.as_chunks::<4>(); + let (chunks_b, residual_b) = other.as_chunks::<4>(); + + // check the residual first to bail out fast if there's a mismatch and comparisons + // happen to be expensive + let mut result = residual_a.into_iter().zip(residual_b).all(|(a, b)| a == b); + + // iter.all short-circuits which means the backend can't unroll the loop due to early exits. + // So we unroll it manually. + result = result + && chunks_a + .iter() + .zip(chunks_b.iter()) + .all(|(a, b)| (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3])); + + result } }