Consteval layout_of caching is surprisingly ineffective
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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