Closed
Description
Summary
The #[derive(PartialEq)]
macro currently compares fields in declaration order, which can lead to suboptimal performance when expensive fields (like references or slices) are compared before cheap fields (like scalars).
This can cause unnecessary memory comparisons (memcmp
/bcmp
) to run even when a cheap field would have determined inequality early.
Reproducible Example
#[repr(C)]
#[derive(PartialEq, Eq)]
pub struct StructA<'a> {
field_1: &'a str, // expensive to compare
field_2: u8, // cheap
}
#[repr(C)]
#[derive(PartialEq, Eq)]
pub struct StructB<'a> {
field_1: u8, // cheap
field_2: &'a str, // expensive
}
pub fn compare_a(a: StructA, b: StructA) -> bool {
a == b
}
pub fn compare_b(a: StructB, b: StructB) -> bool {
a == b
}
Generated Assembly
compare_a
compares the string (bcmp
) before checking theu8
.compare_b
checks theu8
first and avoidsbcmp
on early exit.
See Godbolt for live comparison: https://godbolt.org/z/7a41eT3P3
Meta
- Rust version: stable (1.##) / nightly
- Affects
#[derive(PartialEq)]
macro - Related: optimization of derived traits
Metadata
Metadata
Assignees
Labels
Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)Category: An issue highlighting optimization opportunities or PRs implementing suchIssue: Problems and improvements with respect to performance of generated code.Relevant to the compiler team, which will review and decide on the PR/issue.