Skip to content

Computing crate_hash from metadata encoding instead of HIR (implements #94878) - #154724

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
Daniel-B-Smith:smithdb3/fix-94878
Sep 26, 2026
Merged

rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
Daniel-B-Smith:smithdb3/fix-94878

Conversation

@Daniel-B-Smith

@Daniel-B-Smith Daniel-B-Smith commented Apr 2, 2026 •

Copy link
Copy Markdown
Contributor

View all comments

This PR converts the crate_hash/SVH to depend on metadata instead of HIR whenever metadata is needed. A trimmed down crate_hash is kept for dylib/binary cases where metadata is not present. It is believed that the metadata will be a more sound way to track dependency changes.

Related to #94878

The metadata hash is calculated on the raw bytes before flush because hashing the elements incrementally turned out to be too expensive.

The change to the HIR hash is potentially safe even without the metadata crate_hash change. Without that change, this PR is a performance regression. I am bundling them because I believe the HIR hash change is more likely to be safe in light of the HIR hash being less load bearing on the SVH.

The dylib/binary crate_hash removes components that I believe are not relevant to those cases. Analysis:

  • resolutions.visibilities_for_hashing:

The comment says: "Hash visibility information since it does not appear in HIR." Visibilities only matter to external users of the crate (i.e. consumers of metadata). Without metadata, visibility differences are not observable, so this contributes nothing for incremental correctness.

  • debugger_visualizers:

The comment says: "that content is exported into crate metadata, so any changes to it need to be reflected in the crate hash." Without metadata, there is nothing to export, so this is purely metadata-motivated. The visualizer file path is already covered by HIR (the attribute) and the content is loaded later only if metadata is being written.

  • source_file_names:

These exist solely so that the crate-hash reflects remapped source paths that get embedded into metadata (the comment explicitly says "If we included the full mapping in the SVH, we could only have reproducible builds…"). The remapping itself is already captured via dep_tracking_hash, so for incremental this is redundant.

The crate hash calculation can be reverted via -Z metadata-crate-hash=no. I manually confirmed that setting that flag generates the same hash as the commit prior to my change. The test for that flag only checks that it changes the value of the hash and does not check the specific value of the hash. I could add a check for the latter, but I'm nervous that a hash golden test would be a maintenance headache.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 2, 2026
@rust-log-analyzer

This comment has been minimized.

@Daniel-B-Smith
Daniel-B-Smith force-pushed the smithdb3/fix-94878 branch 5 times, most recently from 24c04d5 to c826667 Compare April 7, 2026 15:59
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@Daniel-B-Smith
Daniel-B-Smith force-pushed the smithdb3/fix-94878 branch 2 times, most recently from 43a7704 to 338aba3 Compare April 8, 2026 19:34
@rust-log-analyzer

This comment has been minimized.

@Daniel-B-Smith
Daniel-B-Smith force-pushed the smithdb3/fix-94878 branch 2 times, most recently from 0ddcd96 to d27cca5 Compare April 8, 2026 21:34
@rust-log-analyzer

This comment has been minimized.

@Daniel-B-Smith
Daniel-B-Smith force-pushed the smithdb3/fix-94878 branch 3 times, most recently from 1e5f269 to 4171895 Compare April 9, 2026 14:56
@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@Daniel-B-Smith Daniel-B-Smith changed the title #94878 Computing crate_hash from metadata encoding instead of HIR (implements #94878) (very draft) Apr 9, 2026
@nnethercote

Copy link
Copy Markdown
Contributor

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Apr 9, 2026
@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@oli-obk

oli-obk commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

@bors r+

@rust-bors

rust-bors Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 56647f0 has been approved by oli-obk

It is now in the queue for this repository.

@rust-bors

This comment has been minimized.

@rust-bors

rust-bors Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

💔 Test for 5ca7eca failed: CI. Failed job:

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

This comment has been minimized.

@Daniel-B-Smith

Copy link
Copy Markdown
Contributor Author

The last failure was due to the proc macro rmake test not working on cross compile. A proc macro is dlopened by the host rustc, so it has to be built for the host, and the the --target added in #139244 doesn't work with this configuration. Since this is solely testing that the SVH is updated correctly, I see no reason to be concerned that SVH generation would be different in cross compilation since all the work is done during the metadata phase.

The ignore-musl is mostly being defensive since it also may not work work for this case, and there isn't any real benefit to test coverage.

Since the diff got rebased into an existing commit, the diff is solely in tests/run-make/proc-macro-dep-source-changes-crate-hash/rmake.rs.

//@ needs-crate-type: proc-macro

was changed into

//@ ignore-cross-compile
//@ needs-crate-type: proc-macro
//@ ignore-musl (FIXME: can't find `-lunwind`)

@jieyouxu

Copy link
Copy Markdown
Member

@bors try jobs=* nolimit

@rust-bors

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

💔 Test for d7ecec7 failed: CI. Failed jobs:

@rustbot

rustbot commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

The SVH is computed by hashing the entire encoded metadata blob, and
SipHash-128 (~2.5 Ir/byte) dominated the cost — it accounted for the whole
of the measured regression on metadata-heavy crates. Switch the byte pass to
XXH3-128, which is ~10x cheaper per byte on its runtime-detected AVX2 path.

XXH3 is non-cryptographic, which is fine here: the SVH is only a change
detector, must be reproducible (so it is never keyed secretly, meaning even
the previous SipHash use was not collision-resistant), and compiling a crate
already executes its build scripts and proc-macros, so the crate author is
trusted regardless. The untracked supplements (dep-tracking hash and the HIR
hash for e.g. DefKind::GlobalAsm) are still folded in via a StableHasher
fingerprint, so coverage is unchanged.

twox-hash 2.x is already in the dependency graph via ruzstd; this only adds a
direct edge (xxhash3_128 + std features for the runtime SIMD dispatch).
@Daniel-B-Smith

Copy link
Copy Markdown
Contributor Author

I fixed tests/run-make/proc-macro-dep-source-changes-crate-hash/rmake.rs but forgot to fix the other two proc-macro tests I added. They have since been fixed.

@oli-obk

oli-obk commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

@bors r+

@rust-bors

rust-bors Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 79ee8dc has been approved by oli-obk

It is now in the queue for this repository.

@rust-bors

This comment has been minimized.

@rust-bors

rust-bors Bot commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

☀️ Test successful - CI
Approved by: oli-obk
Duration: 4h 42m 17s
Pushing 90c195e to main...

@github-actions

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 5ceaf66 (parent) -> 90c195e (this PR)

Test differences

Show 50 test diffs

Stage 1

  • [run-make] tests/run-make/crate-hash-dep-extra-filename: [missing] -> pass (J1)
  • [run-make] tests/run-make/crate-hash-metadata-flag: [missing] -> pass (J1)
  • [run-make] tests/run-make/metadata-stub-incremental-reuse: [missing] -> pass (J1)
  • [run-make] tests/run-make/proc-macro-dep-source-changes-crate-hash: [missing] -> pass (J1)
  • [run-make] tests/run-make/proc-macro-env-changes-crate-hash: [missing] -> pass (J1)
  • [run-make] tests/run-make/proc-macro-global-asm-changes-crate-hash: [missing] -> pass (J1)

Stage 2

  • [run-make] tests/run-make/crate-hash-metadata-flag: [missing] -> pass (J0)
  • [run-make] tests/run-make/proc-macro-dep-source-changes-crate-hash: [missing] -> pass (J0)
  • [run-make] tests/run-make/proc-macro-env-changes-crate-hash: [missing] -> pass (J0)
  • [run-make] tests/run-make/proc-macro-global-asm-changes-crate-hash: [missing] -> pass (J0)
  • [run-make] tests/run-make/crate-hash-metadata-flag: [missing] -> ignore (ignored when cross-compiling) (J2)
  • [run-make] tests/run-make/crate-hash-dep-extra-filename: [missing] -> pass (J3)
  • [run-make] tests/run-make/metadata-stub-incremental-reuse: [missing] -> pass (J3)
  • [run-make] tests/run-make/proc-macro-dep-source-changes-crate-hash: [missing] -> ignore (ignored when cross-compiling) (J4)
  • [run-make] tests/run-make/proc-macro-env-changes-crate-hash: [missing] -> ignore (ignored when cross-compiling) (J4)
  • [run-make] tests/run-make/proc-macro-global-asm-changes-crate-hash: [missing] -> ignore (ignored when cross-compiling) (J4)
  • [run-make] tests/run-make/proc-macro-dep-source-changes-crate-hash: [missing] -> ignore (ignored when the target environment is musl ((FIXME: can't find -lunwind))) (J5)
  • [run-make] tests/run-make/proc-macro-env-changes-crate-hash: [missing] -> ignore (ignored when the target environment is musl ((FIXME: can't find -lunwind))) (J5)
  • [run-make] tests/run-make/proc-macro-global-asm-changes-crate-hash: [missing] -> ignore (ignored when the target environment is musl ((FIXME: can't find -lunwind))) (J5)

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

Job group index

Test dashboard

Run

cargo run --manifest-path src/ci/citool/Cargo.toml -- \
    test-dashboard 90c195e09786b4923a1e4e04216091de639f9fad --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. test-aarch64-apple-macos-26-1: 2h 22m -> 4h 40m (+97.2%)
  2. test-x86_64-gnu-llvm-21-2: 1h 13m -> 1h 47m (+47.3%)
  3. test-x86_64-gnu-llvm-22-1: 55m 59s -> 1h 21m (+45.1%)
  4. test-x86_64-gnu-miri: 1h 31m -> 52m 44s (-42.6%)
  5. test-x86_64-gnu-gcc: 1h 5m -> 1h 31m (+40.6%)
  6. test-x86_64-gnu-aux: 2h 42m -> 1h 36m (-40.4%)
  7. test-x86_64-gnu-parallel-frontend: 1h 28m -> 2h 4m (+39.7%)
  8. test-x86_64-gnu-debug: 2h 10m -> 1h 19m (-38.9%)
  9. dist-i686-linux: 1h 50m -> 1h 10m (-36.5%)
  10. dist-x86_64-msvc: 3h 3m -> 1h 56m (-36.4%)
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 (90c195e): 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)
2.1% [0.2%, 5.8%] 15
Improvements ✅
(primary)
-0.3% [-0.7%, -0.1%] 81
Improvements ✅
(secondary)
-1.1% [-4.6%, -0.1%] 52
All ❌✅ (primary) -0.3% [-0.7%, -0.1%] 81

Max RSS (memory usage)

Results (primary -3.5%, secondary 2.0%)

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

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.2% [2.0%, 4.7%] 6
Improvements ✅
(primary)
-3.5% [-3.5%, -3.5%] 1
Improvements ✅
(secondary)
-1.6% [-2.0%, -1.2%] 2
All ❌✅ (primary) -3.5% [-3.5%, -3.5%] 1

Cycles

Results (primary 13.8%, secondary 2.3%)

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

mean range count
Regressions ❌
(primary)
13.8% [3.1%, 25.3%] 7
Regressions ❌
(secondary)
4.6% [2.1%, 9.0%] 8
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.7% [-4.8%, -2.1%] 3
All ❌✅ (primary) 13.8% [3.1%, 25.3%] 7

Binary size

Results (primary 0.2%, secondary 0.2%)

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

mean range count
Regressions ❌
(primary)
0.2% [0.0%, 0.3%] 33
Regressions ❌
(secondary)
0.2% [0.0%, 0.3%] 49
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.2% [0.0%, 0.3%] 33

Bootstrap: 488.629s -> 487.474s (-0.24%)
Artifact size: 406.21 MiB -> 406.22 MiB (0.00%)

@panstromek

Copy link
Copy Markdown
Contributor

perf triage:

Improvements outweigh regressions. Regressions are secondary, mostly in large-workspace, which is artifical stress tests for dependency overhead in large workspaces.

@rustbot label: +perf-regression-triaged

@Daniel-B-Smith

Copy link
Copy Markdown
Contributor Author

I did some digging, and almost all of the improvements are a reduction in SipHash cost. needs_hir_hash() uses needs_metadata() as a proxy, so the rustdoc code is no longer calculating the HIR hash in some cases. Since the HIR hash getter will fail with an ICE, there's no risk of a subtle regression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CI Area: Our Github Actions CI A-compiletest Area: The compiletest test runner A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-meta Area: Issues & PRs about the rust-lang/rust repository itself A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) A-run-make Area: port run-make Makefiles to rmake.rs A-rustc-dev-guide Area: rustc-dev-guide A-testsuite Area: The testsuite used to check the correctness of rustc A-tidy Area: The tidy tool merged-by-bors This PR was explicitly merged by bors. O-windows Operating system: Windows perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. 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.