rust-lang / rust-lang/rust

Consteval layout_of caching is surprisingly ineffective

Open
#157,010 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-const-eval A-layout C-bug I-compiletime T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

When compiling image@0.25.10 without default features we expected that to be a rather quick affair of 7 additional dependencies, the slowest being num-traits with a build dependency. Instead, it's slow enough for issues being opened in our own issue tracker.

We investigated further and, with perf, found ~12% of build time spent in consteval of which almost all samples fell into InterpCx::layout_of queries. That was curious since we use a few const tables but definitely not of extreme size nor complicated computation and really only with primitive types. Through instrumenting a custom compiler build (printf debugging the types being queried), we found this pattern at the top of the summary:

RDTSC    count  type
-------
2968652 48376   u8
2975486 75647   usize
3372234 2024    std::num::NonZero<usize>
3494159 65639   FnDef(DefId(2:705 ~ core[93c5]::f64::{impl#0}::to_bits), [])
6016422 107343  ()
7589954 145971  FnDef(DefId(21:947 ~ pxfm[d8cc]::common::fmla), [])
10072816        175205  i64
15194244        290049  i32
22053787        392617  u32
22284234        322397  bool
40392452        615785  u64
58157921        2110    std::alloc::Layout
179631693       2996946 f64

Since there are far fewer than 2 million (monomorphized) lines in the whole dependency tree, this points to layouts being evaluated highly redundantly—once per evaluation of at least some statements / expression parts rather than what we'd rather want once per unique definition in MIR.

Meta

rustc --version --verbose:

rustc 1.95.0 (59807616e 2026-04-14)
binary: rustc
commit-hash: 59807616e1fa2540724bfbac14d7976d7e4a3860
commit-date: 2026-04-14
host: x86_64-unknown-linux-gnu
release: 1.95.0
LLVM version: 22.1.2
Development History

In PR https://github.com/rust-lang/rust/pull/156718 I tried the idea of making the queries themselves faster by special-casing primitive types, which have known layouts that can be pre-interned thus replacing a function call with a few moves. This did yield a 2% but ultimately a weird case to make when the problematic behavior is the repetition of queries themselves.

Further instrumentation with the source of each layout call revealed that the vast majority was coming from InterpCx::layout_of_local which is itself more curious due to locals already having a cache attached to it per local that apparently is not hit, most of the time. As pointed out (https://github.com/rust-lang/rust/pull/156718#issuecomment-4528248941) the design would explicitly not work for small const functions called multiple times due to it being attached to the frame of a call, not more directly to a MIR body.

count   source:type
------
164879  layout_of_local:i64
227240  layout_of_local:bool
270325  layout_of_local:u32
579206  layout_of_local:u64
2860447 layout_of_local:f64

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 consteval InterpCx::layout_of and InterpCx::layout_of_local entry points, then reproduce the reported image@0.25.10 build while collecting perf or instrumentation data. Compare the local cache behavior with the intended MIR-body-level reuse. Done means redundant layout queries are substantially reduced and the workload shows an improved consteval/build-time profile.

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.