Skip to content

#[derive(Reflect)] generates excessive amounts of code #19873

@nnethercote

Description

@nnethercote

I recently added a new -Zmacro-stats option to the Rust compiler, which prints measurements on the size of code generated by macros. I soon heard that Bevy's #[derive(Reflect)] is generating large amounts of code.

For example, consider the bevy_ui crate. It is around 16,000 lines of code, and 563,000 bytes of text. Here are the top five entries in the -Zmacro-stats output:

MACRO EXPANSION STATS: bevy_ui
Macro Name                         Uses      Lines  Avg Lines      Bytes  Avg Bytes
-----------------------------------------------------------------------------------
#[derive(Reflect)]                   73     27_407      375.4  1_544_696   21_160.2
#[derive(QueryData)]                  2      1_695      847.5     99_092   49_546.0
#[derive(Component)]                 47      1_368       29.1     70_043    1_490.3
#[derive(Debug)]                     88        930       10.6     38_349      435.8
#[derive(PartialEq)]                 76        792       10.4     34_317      451.5

All the #[derive(Reflect)] invocations in bevy_ui produce more than 1.5MB of source code, an average of 21KB per invocation. That's about 3x the size of the original code, and more than 15x the size of the next biggest derive.

The generated code for a simple example can be seen here. It is very verbose and contains multiple redundancies.

All this code has to be processed by the compiler: parsed, type-checked, borrow-checked, optimized, and codegen'd. Reducing the size of the generated code could improve compile times for Bevy projects significantly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ReflectionRuntime information about typesC-PerformanceA change motivated by improving speed, memory usage or compile timesD-MacrosCode that generates Rust codeS-Needs-InvestigationThis issue requires detective work to figure out what's going wrong

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions