Skip to content

Rollup of 10 perf-sensitive pull requests - #160506

Merged
rust-bors[bot] merged 23 commits into
rust-lang:mainfrom
JonathanBrouwer:rollup-9ScDW58
Aug 4, 2026
Merged

Rollup of 10 perf-sensitive pull requests#160506
rust-bors[bot] merged 23 commits into
rust-lang:mainfrom
JonathanBrouwer:rollup-9ScDW58

Conversation

@JonathanBrouwer

Copy link
Copy Markdown
Contributor

Successful merges:

r? @ghost

Create a similar rollup

xmakro and others added 23 commits June 10, 2026 19:38
By keeping a map from hash to crate number.
Every ObligationCtxt heap-allocated its fulfillment engine as a
Box<dyn TraitEngine>, making it the single largest allocation site in
the compiler (161k allocations on a syn check build, created per
candidate probe in method resolution among others). The solver choice
is a per-session constant and both engine types are small, so store
them inline in a two-variant enum with static dispatch.

The enum's TraitEngine impl needs both FromSolverError bounds, which
ripples to the generic impl blocks and two generic users; the concrete
error types used everywhere implement both. The boxed engine remains
for the per-body typeck root fulfillment context.
Currently it tracks a bit for every `Init`, but it only uses the tracked
data for locals. This means it is tracking data for projections that is
unused.

This commit shrinks the domain to only track data for `Local`s, going
from `MixedBitSet<InitIndex>` to `DenseBitSet<Local>`.

This does regress the error messages in one test:
liveness-assign-imm-local-notes.rs. The next commit will fix that.

The commit also removes some `debug` statements which probably haven't
seen use in a long time. They can be re-added easily if anyone needs
them in the future.
This commit fixes the error message regression in the previous commit by
recomputing flow information at error-reporting time.
`is_local_ever_initialized` is replaced in two ways.
- In `check_access_permissions`: by the new `first_reaching_init`
  function which picks the first init that can reach the error location
  along a path that doesn't cross `StorageDead(local)`.
- In `add_used_mut`: by a simple `contains` test.
Co-Authored-By: Matthieu M <matthieum.147192@gmail.com>
…n-impls, r=jackh726

perf: skip irrelevant foreign impls when building the specialization graph

Skip foreign non-blanket impls that can't overlap any local impl when building the specialization graph. The call site showed up when profiling and this PR leads to a mean -1.5% instructions perf improvement, see rust-lang#157281 (comment)
…li-obk

Next steps for FnDef binder changes (instantiate most FnDef binders)

This change is a part of the ongoing effort to clean up binder/turbofishing behavior in the compiler (rust-lang#156581).

This PR instantiates binders that were previously created via `ty::Binder::dummy()` with meaningfully bound vars.

r? oli-obk

> Call me Turbofishmael.
Some years ago- never mind how long precisely-
having little or no money in my purse,
and nothing particular to interest me in C++,
I thought I would sail about a little and see the rusty part of the world.
Optimize crate resolution for large workspace

By keeping a map from hash to crate number.
…jgillot

Speed up `EverInitializedPlaces`

By simplifying its domain. Details in individual commits.

r? @cjgillot
…r=nnethercote

perf: store the fulfillment engine inline in ObligationCtxt

Every `ObligationCtxt` allocated its fulfillment engine on the heap as a `Box<dyn TraitEngine>`. This was the single largest allocation site in the compiler: 161k allocations on a `syn` check build (measured with DHAT). `ObligationCtxt`s are created in hot paths, for example once per candidate probe during method resolution.

The allocation is easy to avoid. Which solver is used never changes during a compilation session, and both engine types are small (the obligation forest allocates its own storage separately). So this PR stores the engine directly inside `ObligationCtxt`, in a two-variant enum. Calls now go through a match on that enum instead of virtual dispatch.

The enum's `TraitEngine` impl needs both `FromSolverError` bounds, so a few generic impl blocks and two generic users now need both bounds as well. The concrete error types used in practice already implement both, so nothing else changes for callers. The typeck root fulfillment context keeps the boxed engine; it is created once per function body, so the allocation does not matter there.
…e-cache, r=petrochenkov

perf: Cache already-checked types in the privacy visitor

The privacy checker walks the full type of every expression and pattern in a module, re-walking the same type once per node it appears on. This caches the types that walked clean (no privacy error) and skips them next time. A walk's result depends only on the interned type and the fixed module being checked, so a type that walks clean once walks clean everywhere.

Only clean walks are cached, so nothing is lost: a type that errors is never cached and still fires at every span, and no dep-graph edges are dropped since the full walk already ran once in the same query.
… r=oli-obk

interpret: skip deref-projection validity checks when they are not needed

Trying to claw back the perf regression from rust-lang#160012.

We could also, like, skip the entire check in const-eval when we don't care about validity. But the slowdown will also affect Miri so I want to first try what we can do without doing less UB checking.
Deduplicate target and host filesearch

I was looking into preprocessing the search directories somehow, so that both host and target don't have to scan them. However, it would be a bit annoying, because they don't share the tlib path. But then I noticed that the code already used `Arc` for `SearchPath`, which was essentially the same optimization, which made sense before rust-lang#158823. But after that PR, it doesn't make sense to put `SearchPath` into `Arc`, because it doesn't really do anything, and the complex logic moved into `FileSearch`. So this PR puts that under `Arc`, to avoid doing duplicated work in the common case, where `host == target`.

r? petrochenkov
Add fast path to `escape_string_symbol`

Discussed in rust-lang#159916. So far used the manual escaping variant.

CC @matthieu-m

r? the8472
Add offload guard flags to typeck to prevent perf regressions

Fixes perf regression in rust-lang#158693

r? @ZuseZ4
@rust-bors rust-bors Bot added the rollup A PR which is a rollup label Aug 4, 2026
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Aug 4, 2026
@JonathanBrouwer JonathanBrouwer changed the title Rollup of 10 pull requests Rollup of 10 perf-sensitive pull requests Aug 4, 2026
@JonathanBrouwer

Copy link
Copy Markdown
Contributor Author

@bors r+ p=5

Trying commonly failed jobs
@bors try jobs=dist-various-1,test-various,x86_64-gnu-aux,x86_64-gnu-llvm-21-3,x86_64-msvc-1,aarch64-apple,x86_64-mingw-1,i686-msvc-*

@rust-bors

rust-bors Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

📌 Commit d1cef67 has been approved by JonathanBrouwer

It is now in the queue for this repository.

🌲 The tree is currently closed for pull requests below priority 10. This pull request will be tested once the tree is reopened.

Reason for tree closure: manually handling queue due to backlog

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 4, 2026
rust-bors Bot pushed a commit that referenced this pull request Aug 4, 2026
Rollup of 10 perf-sensitive pull requests


try-job: dist-various-1
try-job: test-various
try-job: x86_64-gnu-aux
try-job: x86_64-gnu-llvm-21-3
try-job: x86_64-msvc-1
try-job: aarch64-apple
try-job: x86_64-mingw-1
try-job: i686-msvc-*
@rust-bors

This comment has been minimized.

@JonathanBrouwer

Copy link
Copy Markdown
Contributor Author

This is a rollup of 10 perf-sensitive pull requests, because the queue of them got a bit too large
See #t-infra > Tree ops @ 💬 for context

@Kobzol

Kobzol commented Aug 4, 2026

Copy link
Copy Markdown
Member

@bors p=10

scheduling

@rust-bors

This comment has been minimized.

@panstromek

Copy link
Copy Markdown
Contributor

If this succeeds, it will be the greenest rollup in the history of the observable universe.

@rust-bors

rust-bors Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: 9854f45 (9854f45972cfda36b7b73a1fded279b47f183458)
Base parent: 0b63def (0b63defc8fd68957c635fe61f097b84df8fd9611)

@rust-bors rust-bors Bot added merged-by-bors This PR was explicitly merged by bors. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 4, 2026
@rust-bors

rust-bors Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

☀️ Test successful - CI
Approved by: JonathanBrouwer
Duration: 3h 10m 48s
Pushing 1ed2df6 to main...

@rust-bors
rust-bors Bot merged commit 1ed2df6 into rust-lang:main Aug 4, 2026
15 checks passed
@rustbot rustbot added this to the 1.99.0 milestone Aug 4, 2026
@rust-timer

Copy link
Copy Markdown
Collaborator

📌 Perf builds for each rolled up PR:

PR# Message Perf Build Sha
#157281 perf: skip irrelevant foreign impls when building the speci… 6e2e027ff5a529a0e76b0422f07cd90391b797fe (link)
#159403 Next steps for FnDef binder changes (instantiate most FnDef… ec3341f09f1325d94135d5f3a66c430b8902a226 (link)
#159763 Optimize crate resolution for large workspace 2f596f7ab18a4d7786cd843bf58086b870f17830 (link)
#160033 Speed up EverInitializedPlaces 65b521b91142fb4de8d491417c750ad195456b38 (link)
#160268 perf: store the fulfillment engine inline in ObligationCtxt 2d4494f87ae873217d0ebad0e99f57083a4041bb (link)
#160317 perf: Cache already-checked types in the privacy visitor 76908bcafd15023a73e988caed101cebc2643e2d (link)
#160399 interpret: skip deref-projection validity checks when they … 6e167bd0f0e572fbc1452cde083bc6e1b0e3d440 (link)
#160451 Deduplicate target and host filesearch 68be5aa0f6d7443e9eea6db179d6df39b0840b49 (link)
#160453 Add fast path to escape_string_symbol 5f46ebd880ace77622d8b4a2de67f55eac6cb0f4 (link)
#160454 Add offload guard flags to typeck to prevent perf regressio… d41deaab2cf1f0dbf9667f3aa190e3a18cff7ab3 (link)

previous master: 0b63defc8f

In the case of a perf regression, run the following command for each PR you suspect might be the cause: @rust-timer build $SHA

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing 0b63def (parent) -> 1ed2df6 (this PR)

Test differences

Show 42 test diffs

42 doctest diffs were found. These are ignored, as they are noisy.

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard 1ed2df61a19042f231709eb05d032ae9e2cb2084 --output-dir test-dashboard

And then open test-dashboard/index.html in your browser to see an overview of all executed tests.

Job duration changes

  1. x86_64-gnu-gcc-core-tests: 8m 2s -> 14m 37s (+81.7%)
  2. i686-gnu-1: 1h 21m -> 2h 25m (+79.3%)
  3. dist-x86_64-llvm-mingw: 1h 24m -> 2h 5m (+49.0%)
  4. test-various: 1h 18m -> 1h 55m (+47.8%)
  5. x86_64-gnu-gcc: 49m 2s -> 1h 11m (+45.5%)
  6. x86_64-gnu-parallel-frontend: 1h 31m -> 2h 12m (+45.1%)
  7. dist-i686-mingw: 1h 59m -> 2h 50m (+42.7%)
  8. arm-android: 1h 16m -> 1h 47m (+39.9%)
  9. x86_64-gnu: 1h 56m -> 2h 41m (+38.5%)
  10. i686-msvc-1: 2h 10m -> 2h 53m (+32.6%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (1ed2df6): comparison URL.

Overall result: ❌✅ regressions and improvements - please read:

Our benchmarks found a performance regression caused by this PR.
This might be an actual regression, but it can also be just noise.

Next Steps:

  • If the regression was expected or you think it can be justified,
    please write a comment with sufficient written justification, and add
    @rustbot label: +perf-regression-triaged to it, to mark the regression as triaged.
  • If you think that you know of a way to resolve the regression, try to create
    a new PR with a fix for the regression.
  • If you do not understand the regression or you think that it is just noise,
    you can ask the @rust-lang/wg-compiler-performance working group for help (members of this group
    were already notified of this PR).

@rustbot label: +perf-regression
cc @rust-lang/wg-compiler-performance

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.5% [0.5%, 0.5%] 1
Improvements ✅
(primary)
-1.7% [-6.2%, -0.2%] 237
Improvements ✅
(secondary)
-4.7% [-34.7%, -0.1%] 230
All ❌✅ (primary) -1.7% [-6.2%, -0.2%] 237

Max RSS (memory usage)

Results (primary -1.9%, secondary -2.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
3.1% [0.9%, 5.1%] 4
Regressions ❌
(secondary)
2.1% [0.4%, 8.0%] 12
Improvements ✅
(primary)
-2.1% [-6.7%, -0.5%] 130
Improvements ✅
(secondary)
-2.8% [-7.6%, -0.4%] 83
All ❌✅ (primary) -1.9% [-6.7%, 5.1%] 134

Cycles

Results (primary -3.7%, secondary -6.6%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.5% [0.5%, 0.5%] 1
Regressions ❌
(secondary)
7.3% [0.6%, 14.0%] 2
Improvements ✅
(primary)
-3.7% [-8.2%, -0.6%] 86
Improvements ✅
(secondary)
-6.9% [-22.4%, -0.4%] 102
All ❌✅ (primary) -3.7% [-8.2%, 0.5%] 87

Binary size

Results (primary 0.1%, secondary 0.3%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.1% [0.0%, 0.5%] 104
Regressions ❌
(secondary)
0.3% [0.0%, 0.9%] 59
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.1% [0.0%, 0.5%] 104

Bootstrap: 489.577s -> 489.825s (0.05%)
Artifact size: 390.24 MiB -> 391.14 MiB (0.23%)

@rustbot rustbot added the perf-regression Performance regression. label Aug 4, 2026
@JonathanBrouwer

JonathanBrouwer commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@rustbot label: +perf-regression-triaged
Regression is not worth hunting down, I think we can consider running perf jobs on all 10 components of this rollup to verify the perf improvements were as intended and there is no masking of perf regressions going on though. This is currently blocked on perf builds working, see #t-infra > Making dist-x86_64-linux job faster @ 💬

@rustbot rustbot added the perf-regression-triaged The performance regression has been triaged. label Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. rollup A PR which is a rollup T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants