Skip to content

#[derive(PartialEq)] does not reorder field comparisons to improve performance #141141

Closed
@Sol-Ell

Description

@Sol-Ell

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 the u8.
  • compare_b checks the u8 first and avoids bcmp 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

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions