rust-lang / rust-lang/rust

Excessive rustc memory usage and compile time

Open
#157,764 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-compilemem I-compiletime T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Summary

When a crate defines a large number of bitflags! types, rustc memory consumption and compilation time grow approximately linearly with the number of generated types. The growth is large enough to make real-world scenarios hit practical memory limits.

The issue appears to be primarily related to the number of generated trait implementations, as the bitflags! macro generates implementations for several traits (such as Add, Sub, BitOr, etc.) for the type.

Reproducer

Cargo.toml

[package]
name = "rustc-mem-measure"
version = "0.1.0"
edition = "2024"

[dependencies]
bitflags = "2.13.0"

src/lib.rs

use bitflags::bitflags;

macro_rules! create_bitflags_instance {
    ($name:ident) => {
        bitflags! {
            pub struct $name: u64 {
                const BIT0  = 1 << 0;
                const BIT1  = 1 << 1;
                const BIT2  = 1 << 2;
                const BIT3  = 1 << 3;
                const BIT4  = 1 << 4;
                const BIT5  = 1 << 5;
                const BIT6  = 1 << 6;
                const BIT7  = 1 << 7;
            }
        }
    };
}

create_bitflags_instance!(Type0);
create_bitflags_instance!(Type1);
create_bitflags_instance!(Type2);
create_bitflags_instance!(Type3);
create_bitflags_instance!(Type4);
create_bitflags_instance!(Type5);
create_bitflags_instance!(Type6);
create_bitflags_instance!(Type7);
create_bitflags_instance!(Type8);
create_bitflags_instance!(Type9);
// ...

Note that the create_bitflags_instance! macro is only used to simplify the example. Replacing it with manually written type definitions has only a minimal effect on resource consumption.

Observed scaling

Type count Memory usage (MB) Time (s)
1 33.3 0.2
10 63.2 1.0
100 393.5 9.7
1000 4391.5 104.6

Memory usage and compile time both scale approximately linearly with the number of generated bitflags! types.

Toolchain

The measurements were collected using a custom debug-built toolchain (dc375db7d8df0aa450e622c529147c95eee756f5). However, similar behavior is observed across multiple toolchain versions, including Rust 1.80 through the latest stable available at the time of writing (1.96.0 (30a34c682 2026-05-25)).

Profiling information

Using the debug-built toolchain, the largest memory consumers observed in the rustc process were:

MB % of useful heap Consumer
797.7 18.16% 2,714 places below Massif threshold
502.4 11.44% rustc_resolve::Module::for_each_child / Resolver::finalize_imports
438.5 9.99% rustc_arena::DroplessArena::grow
386.6 8.80% rustc_middle::dep_graph::CurrentDepGraph::record_edge
367.7 8.37% indexmap::Core<rustc_span::SpanData, ()>::insert_full

Real-world impact

This issue was discovered while developing the Arm system register crate: arm-sysregs The crate generates types and accessors for Armv8-A system registers. Currently only about 25% of the registers are covered, yet builds are already approaching CI memory limits (~3 GB).

The current scaling is therefore problematic because:

  • Memory requirements continue to grow as more registers are added. When the crate is complete, the extrapolated memory usage of rustc will be ~12GB.
  • Downstream projects compiling the crate inherit the cost.
  • Parallel builds amplify the problem because multiple rustc processes compete for memory simultaneously.

Questions

  1. Are there known coding patterns in bitflags!-generated code that contribute disproportionately to memory usage and should be avoided?
  2. Are there ongoing or planned efforts to reduce rustc memory consumption for workloads involving large numbers of types and trait implementations?
  3. The profiling results suggest significant memory usage in dependency graph tracking and related compiler infrastructure. Would it be feasible to introduce more cache-like behavior where less frequently used entries can be discarded and recomputed when necessary, rather than retaining all information for the duration of compilation?
  4. Are there alternative approaches, compiler flags, or code-generation patterns that could mitigate this issue?

Expected outcome

  • rustc memory usage for this pattern could be reduced substantially, or
  • Guidance could be provided on which language/library patterns are responsible for the scaling and how generated code can be structured to avoid them.

Any suggestions for investigation or mitigation would be greatly appreciated.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Cargo.toml and src/lib.rs reproducer, varying the number of generated bitflags types and recording rustc memory and compile time. Use the listed profiling consumers, including rustc_resolve::Module::for_each_child, rustc_middle::dep_graph::CurrentDepGraph::record_edge, and rustc_arena::DroplessArena::grow, to identify where scaling occurs. Done means characterizing the cause and either demonstrating a substantial reduction or documenting a concrete mitigation or guidance.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.