Repository navigation
Description
Warning
If you are looking to submit an experience report, note that you should not be setting anything via RUSTFLAGS; you should be setting this via either the Cargo profile setting in your top-level crate for a specific dependency, or the Cargo [hints] table in a specific dependency.
Summary
Implementation: #15643, #15673
Documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-hint-mostly-unused-option
This feature provides a new option in the [profile] section to enable the rustc hint-mostly-unused option. This is primarily useful to enable for specific dependencies:
[profile.dev.package.huge-mostly-unused-dependency]
hint-mostly-unused = trueTo enable this feature, pass -Zprofile-hint-mostly-unused. However, since this option is a hint, using it without passing -Zprofile-hint-mostly-unused will only warn and ignore the profile option. Versions of Cargo prior to the introduction of this feature will give an "unused manifest key" warning, but will otherwise function without erroring. This allows using the hint in a crate's Cargo.toml without mandating the use of a newer Cargo to build it.
Unresolved Issues
- Test handling of this in a profile in
.cargo/config.toml -
cargo publishstrippinghintssection from Cargo.toml #15836 - lint for overly broad applications in profile being stable (https://doc.rust-lang.org/nightly/cargo/reference/lints.html#blanket_hint_mostly_unused)
Future Extensions
In the future, we may also want to provide a way for a crate to hint that it should have this option turned on by default, unless overridden by the top-level crate.
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
biruburu commentedon Jul 15, 2025
papow65 commentedon Jul 15, 2025
Kobzol commentedon Jul 15, 2025
Just noting, in case it wasn't clear from the blog post, applying this flag to all your dependencies will most likely make your compilation times be terrible. It is designed to be only applied to a handful of selected large dependencies whose code is mostly unused in your crate graph. You should pass the flag to these dependencies using Cargo (https://blog.rust-lang.org/inside-rust/2025/07/15/call-for-testing-hint-mostly-unused/#plumbing-this-through-cargo-with-profiles).
Arnavion commentedon Jul 16, 2025
ze commentedon Jul 16, 2025
Tried on a crate of mine. I specifically only tried it on
aws-sdk-s3.cargo 1.90.0-nightly (eabb4cd92 2025-07-09)Each run had a
cargo cleanran. There were two runs done.Before:
After:
To get a baseline on
cargo 1.88.0 (873a06493 2025-05-10):This looks great! 💯.
cemoktra commentedon Jul 16, 2025
workingjubilee commentedon Jul 16, 2025
@cemoktra How did you enable it?
Did you (incorrectly) add it to RUSTFLAGS as in #15644 (comment) or?
Per the blog post:
cemoktra commentedon Jul 16, 2025
omid commentedon Jul 16, 2025
JarredAllen commentedon Jul 16, 2025
On a decently-large project at my work (a bit over 1k crates including transitive dependencies, a bit over 100 binaries), I tested using
cargo clean && time cargo build --workspace, oncargo 1.90.0-nightly (eabb4cd92 2025-07-09).Without this flag:
(a second try had a user time of 46m26s and a system time of 6m5s, so there's some variation, but small enough that I believe the results below are real differences)
When I applied the flag to tokio:
When I applied it to all of my dependencies:
It looks like this setting makes things take longer when applied indiscriminately, but it saves time when applied to the right crates. Just applying it to tokio was a 3% speedup on the entire build process, and I'd guess there are other, equally-sized wins in my dependency tree if I looked closer. (I think user and system times are the right values to look at, since I ran it on my laptop that has various background tasks that could interfere with the real time)
As a note, I applied it to all dependencies by putting this in my workspace-level
Cargo.tomlfile:And I applied it just to tokio by doing the same thing but with
tokioinstead of"*".workingjubilee commentedon Jul 16, 2025
@omid @cemoktra Your reports are invalid. The RUSTFLAGS command is not the correct way to handle this.
Arnavion commentedon Jul 17, 2025
I put
[hints] mostly-unused = truein k8s-openapi's Cargo.toml and then did a clean build of its two internal test suite crates withcargo test -Zprofile-hint-mostly-unused --no-run --timings .... k8s-openapi is a very large crate (auto-generated bindings from Kubernetes' OpenAPI spec) but the tests use a very small fraction of its types. For the sake of reproducability, these were the steps:Use this commit (nothing special about it, just latest master at the moment).
Add
[hints] mostly-unused = trueto the root Cargo.tomlRun:
Results, including the two
--timingsoutputs:Without the hint, without
-j 1: ~23sWith the hint, without
-j 1: ~20sWithout the hint, with
-j 1: ~58sWith the hint, with
-j 1: ~49sWithout the hint, with
-j 1, with--release: ~144sWith the hint, with
-j 1, with--release: ~101slexeyOK commentedon Jul 17, 2025
I used hints on ferrumc-rs/ferrumc repository adding this to Cargo.toml
the release compile time improved from 506s to 367s (-26%) on 4 core machine (old)
i was calling cargo with
cargo build -r -Zprofile-hint-mostly-unused --timingshere are the timings: timings.zip
saethlin commentedon Jul 17, 2025
@lexeyOK How did you come up with that list of crates to apply the hint to? Instinct? Or did you test each one?
lexeyOK commentedon Jul 17, 2025
@saethlin
i picked the top crates with high codegen ratio from timings report + some experimentation
also other developer seems to not have any improvement with their's high end machine 😕 (codegen is fast on their end)
TypeLevelConsoli commentedon Jul 24, 2025
I know I'm using it incorrectly, but when I enable
rustflags = ["-Zhint-mostly-unused"]in.cargo/config.tomlon anaxumAPI project usingutoipaandutoipa-swagger-ui, the project fails to compile with afree(): invalid pointerwhile attempting to download the UI during the build script.the error
You can reproduce the error by
cargo building this project https://github.com/TypeLevelConsoli/mostly-unused-vs-swagger--cargo-errorIf you remove the
-Zhint-mostly-unused, everything compiles without any issues.saethlin commentedon Jul 24, 2025
I can't reproduce that error. @TypeLevelConsoli can you file a bug on http://github.com/rust-lang/rust/issues/ and include what distro you are using? My instinct is that the bug you found is only exposed by the particular system libraries or linkage that is happening in your build. I'm hoping that just the distro/version is enough to cobble together a reproducer in Docker.
TypeLevelConsoli commentedon Jul 24, 2025
I was able to narrow it down a bit. The issue only happens when I mix
-Zhint-most-unusedandopt-level={1,2,3}(I had it set on my global config). That's probably why you couldn't reproduce it, @saethlin! (I updated the repo if you want to test again :))saethlin commentedon Jul 24, 2025
Yes, I can reproduce the crash now.
MarijnS95 commentedon Aug 10, 2025
As the maintainer of
ash(low-level Vulkan bindings crate), we're also frequently plagued by (user reports of) relatively slow compiletimes for a rather large API surface that most users will not use (i.e. all Vulkan extensions under the sun). Per the blog-post, I'll share my findings here (also in case I'm doing something wrong). The nightly version isrustc 1.89.0 (29483883e 2025-08-04).If I understand this correctly the effect should apply to downstream consumers of this library crate, so I'm profiling this against our
ash-examplescrate rather than the library crate directly.Tip
EDIT: as it turns out this speedup applies to building the library crate directly as well, and my testing methodology was wrong; the clean build time of
ash-exampleswas dominated by many smaller dependency crates. Changing the test to first build the crate once, then cleaning just the library crate usingcargo clean -p ashbefore each test shows the same ±600ms speedup on the example, as we saw on the library as well. Results below have been rewritten.On my machine I've cloned https://github.com/ash-rs/ash at the latest commit ash-rs/ash@e044ecd1, and used the following command for a baseline test:
Then added this to
ash/Cargo.toml:And re-ran the benchmark together with
-Zprofile-hint-mostly-unusedflag:That looks to be a nice ±600ms compile-time improvement for our library crate 🎉.
More or less coincidentally, also for completeness, I performed the same test against the library crate. Baseline:
And with
[hints] mostly-unused = true:That's the same ±600ms improvement.
kleinesfilmroellchen commentedon Sep 12, 2025
Testing on penplot, I expected to get significant gains from enabling this on
coreandalloc(which need to be specially-built and optimized for my target platformriscv64imac-unknown-none-elf), as well as some of the HAL crates (esp-hal, variousembassycrates). However, among the slow crates I individually tested (going off of a cleancargo --timingsreport) only minor improvements were achievable in debug builds as follows:base: 47.33s
esp-hal: 49.34s
esp-wifi: 48.06s
picoserve: 48.07s
uom: 46.55s
alloc: 48.25s
core: 50.88s
darling-core: 47.12s
pest: 47.71s
object: 47.16s
uom+object+darling-core (all the ones with individual improvements): 47.14s
Note that the debug build is still optimization level
s, and even optimization level3foresp-wifi(recommended by upstream since Wifi often cannot connect otherwise). For the release build I only tested clean and the combination of the “good candidates”:base: 51.47s
uom+object+darling-core: 51.65s
No useful speedups for me over here in embedded land, quite a bit of this is down to measurement noise. For reference,
-Zthreads=nproc(20x Xeon E5-2680) provides a 37% speedup on debug builds.It’s also hard to gauge which crates would really benefit; I did also check
syn,serdeandlibmbut several others (esp32c6,data-encoding,smoltcp) seem like candidates. Unfortunately I don’t have the energy to single-step-test through my entire 270-crate graph with 1+ minute per clean rebuild :)Never in my testing did I observe any bugs, no crashes or changed on-target behavior.
Hope this is useful data!
joshtriplett commentedon Apr 21, 2026
@nikomatsakis came up with a clever idea to improve this.
Currently, hint-mostly-unused uses the inline machinery. We could, instead, use the monomorphization machinery. (If the function isn't already generic, we could act as if it needs a generic parameter like
<()>.). If it gets called, we monomorphize it. This would have the same net effect, but with three major advantages:That seems like a win across the board.
saethlin commentedon Apr 22, 2026
I think you're confused by the name
cross_crate_inlinable. That query is an integral part of instantiation mode selection, and it only interacts with MIR inlining because MIR inlining needs to not change symbol visibility.I would be happy to see some renaming.
I think what you are looking for is to assign these items GloballyShared-with-conflict-avoidance instantiation then also make them exported symbols like share-generics.
joshtriplett commentedon Apr 22, 2026
@saethlin Thank you for the correction; I think the name did indeed throw me off quite a bit.
I'll take a look at that.