Skip to content

Tracking Issue for profile-hint-mostly-unused #15644

@joshtriplett

Description

@joshtriplett
Member

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 = true

To 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

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.

Activity

biruburu

biruburu commented on Jul 15, 2025

@biruburu
papow65

papow65 commented on Jul 15, 2025

@papow65
Kobzol

Kobzol commented on Jul 15, 2025

@Kobzol
Member

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

Arnavion commented on Jul 16, 2025

@Arnavion
ze

ze commented on Jul 16, 2025

@ze

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 clean ran. There were two runs done.

Before:

run1: 4m 20s
run2: 4m 06s

After:

run1: 3m 32s
run2: 3m 18s

To get a baseline on cargo 1.88.0 (873a06493 2025-05-10):

run1: 4m 12s
run2: 4m 14s

This looks great! 💯.

cemoktra

cemoktra commented on Jul 16, 2025

@cemoktra
workingjubilee

workingjubilee commented on Jul 16, 2025

@workingjubilee
Member

@cemoktra How did you enable it?

Did you (incorrectly) add it to RUSTFLAGS as in #15644 (comment) or?

Per the blog post:

Please report any performance improvements, or unexpected performance issues, or especially any failures you observe, to the #15644. When reporting, please tell us:

  • What hints or profile settings you added
  • What crates you added them to
  • What top-level crate you're building
  • What features you set when building
  • What build profile you're using (e.g. the default dev profile, or the release profile)
  • Whether you did a clean build or an incremental rebuild
  • What performance numbers you got with and without the option you added
cemoktra

cemoktra commented on Jul 16, 2025

@cemoktra
omid

omid commented on Jul 16, 2025

@omid
JarredAllen

JarredAllen commented on Jul 16, 2025

@JarredAllen

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, on cargo 1.90.0-nightly (eabb4cd92 2025-07-09).

Without this flag:

real    4m27.345s
user    45m39.633s
sys     5m59.555s

(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:

real    4m14.523s                                           
user    44m39.785s                                          
sys     5m49.740s                                           

When I applied it to all of my dependencies:

real    4m22.295s
user    47m22.738s
sys     6m4.903s

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.toml file:

[profile.dev.package."*"]
hint-mostly-unused = true

And I applied it just to tokio by doing the same thing but with tokio instead of "*".

workingjubilee

workingjubilee commented on Jul 16, 2025

@workingjubilee
Member

@omid @cemoktra Your reports are invalid. The RUSTFLAGS command is not the correct way to handle this.

Arnavion

Arnavion commented on Jul 17, 2025

@Arnavion

I put [hints] mostly-unused = true in k8s-openapi's Cargo.toml and then did a clean build of its two internal test suite crates with cargo 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:

  1. Use this commit (nothing special about it, just latest master at the moment).

  2. Add [hints] mostly-unused = true to the root Cargo.toml

  3. Run:

    git clean -xffd &&
    time bash -c '
        # test suite 1
        (cd k8s-openapi-tests && cargo test -Zprofile-hint-mostly-unused --no-run --timings --features test_v1_33) &&
    
        # test suite 2
        (cd k8s-openapi-tests-macro-deps && cargo test -Zprofile-hint-mostly-unused --no-run --timings --features test_v1_33)
    '

Results, including the two --timings outputs:

  • Without the hint, without -j 1: ~23s

    k8s-openapi v0.25.0 ; Total: 7.1s ; Codegen: 1.1s (16%) ; Features: default, schemars, std, v1_33
    k8s-openapi v0.25.0 ; Total: 7.1s ; Codegen: 1.1s (16%) ; Features: schemars, v1_33

  • With the hint, without -j 1: ~20s

    k8s-openapi v0.25.0 ; Total: 6.0s ; Codegen: 0.2s (3%) ; Features: default, schemars, std, v1_33
    k8s-openapi v0.25.0 ; Total: 5.8s ; Codegen: 0.2s (3%) ; Features: schemars, v1_33

  • Without the hint, with -j 1: ~58s

    k8s-openapi v0.25.0 ; Total: 10.5s ; Codegen: 4.7s (45%) ; Features: default, schemars, std, v1_33
    k8s-openapi v0.25.0 ; Total: 10.6s ; Codegen: 4.7s (45%) ; Features: schemars, v1_33

  • With the hint, with -j 1: ~49s

    k8s-openapi v0.25.0 ; Total: 5.9s ; Codegen: 0.2s (3%) ; Features: default, schemars, std, v1_33
    k8s-openapi v0.25.0 ; Total: 5.9s ; Codegen: 0.2s (3%) ; Features: schemars, v1_33

  • Without the hint, with -j 1, with --release: ~144s

    k8s-openapi v0.25.0 ; Total: 27.8s ; Codegen: 22.3s (80%) ; Features: default, schemars, std, v1_33
    k8s-openapi v0.25.0 ; Total: 27.7s ; Codegen: 22.1s (80%) ; Features: schemars, v1_33

  • With the hint, with -j 1, with --release: ~101s

    k8s-openapi v0.25.0 ; Total: 5.5s ; Codegen: 0.1s (2%) ; Features: default, schemars, std, v1_33
    k8s-openapi v0.25.0 ; Total: 5.6s ; Codegen: 0.1s (2%) ; Features: schemars, v1_33


$ cargo --version

cargo 1.90.0-nightly (6833aa715 2025-07-13)

$ rustc -vV

rustc 1.90.0-nightly (5795086bd 2025-07-16)
binary: rustc
commit-hash: 5795086bdfe7ed988aa53a110bd0692c33d8755b
commit-date: 2025-07-16
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.8
lexeyOK

lexeyOK commented on Jul 17, 2025

@lexeyOK

I used hints on ferrumc-rs/ferrumc repository adding this to Cargo.toml

[profile.release.package]
bevy_ecs = { hint-mostly-unused = true }
regex = { hint-mostly-unused = true }
toml_edit = { hint-mostly-unused = true }
tokio = { hint-mostly-unused = true }
reqwest = { hint-mostly-unused = true }
serde = { hint-mostly-unused = true }
console-subscriber = { hint-mostly-unused = true }
bevy_reflect = { hint-mostly-unused = true }
rustls = { hint-mostly-unused = true }
regex-automata = { hint-mostly-unused = true }
backtrace = { hint-mostly-unused = true }
ureq = { hint-mostly-unused = true }
clap_builder = { hint-mostly-unused = true }
tonic = { hint-mostly-unused = true }
tracing = { hint-mostly-unused = true }
axum = { hint-mostly-unused = true }
figment = { hint-mostly-unused = true }
toml = { hint-mostly-unused = true }
time = { hint-mostly-unused = true }
dhat = { hint-mostly-unused = true }
encoding_rs = { hint-mostly-unused = true }

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 --timings

cargo 1.90.0-nightly (6833aa715 2025-07-13)
rustc 1.90.0-nightly (5795086bd 2025-07-16)
CPU: Intel(R) Core(TM) i5 650 (4) @ 3.20 GHz

here are the timings: timings.zip

saethlin

saethlin commented on Jul 17, 2025

@saethlin
Member

@lexeyOK How did you come up with that list of crates to apply the hint to? Instinct? Or did you test each one?

lexeyOK

lexeyOK commented on Jul 17, 2025

@lexeyOK

@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

TypeLevelConsoli commented on Jul 24, 2025

@TypeLevelConsoli

I know I'm using it incorrectly, but when I enable rustflags = ["-Zhint-mostly-unused"] in .cargo/config.toml on an axum API project using utoipa and utoipa-swagger-ui, the project fails to compile with a free(): invalid pointer while attempting to download the UI during the build script.

the error

error: failed to run custom build command for `utoipa-swagger-ui v9.0.2`

Caused by:
  process didn't exit successfully: `/tmp/mostly-unused-vs-swagger/target/debug/build/utoipa-swagger-ui-3f0ec099b909af26/build-script-build` (signal: 6, SIGABRT: process abort signal)
  --- stdout
  OUT_DIR: /tmp/mostly-unused-vs-swagger/target/debug/build/utoipa-swagger-ui-5fc864049fc8e730/out
  SWAGGER_UI_DOWNLOAD_URL: https://github.com/swagger-api/swagger-ui/archive/refs/tags/v5.17.14.zip
  cargo:rerun-if-env-changed=SWAGGER_UI_DOWNLOAD_URL
  start download to: "/tmp/mostly-unused-vs-swagger/target/debug/build/utoipa-swagger-ui-5fc864049fc8e730/out/v5.17.14.zip"
  reqwest feature: Err(NotPresent)
  trying to download using `curl` system package

  --- stderr
  free(): invalid pointer

You can reproduce the error by cargo building this project https://github.com/TypeLevelConsoli/mostly-unused-vs-swagger--cargo-error

If you remove the -Zhint-mostly-unused, everything compiles without any issues.

saethlin

saethlin commented on Jul 24, 2025

@saethlin
Member

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

TypeLevelConsoli commented on Jul 24, 2025

@TypeLevelConsoli

I was able to narrow it down a bit. The issue only happens when I mix -Zhint-most-unused and opt-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

saethlin commented on Jul 24, 2025

@saethlin
Member

Yes, I can reproduce the crash now.

MarijnS95

MarijnS95 commented on Aug 10, 2025

@MarijnS95

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 is rustc 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-examples crate 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-examples was dominated by many smaller dependency crates. Changing the test to first build the crate once, then cleaning just the library crate using cargo clean -p ash before 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:

hyperfine -s 'cargo +nightly b -p ash-examples' -p 'cargo clean -p ash' 'cargo +nightly b -p ash-examples'
Benchmark 1: cargo +nightly b -p ash-examples
  Time (mean ± σ):      7.187 s ±  0.063 s    [User: 7.242 s, System: 1.293 s]
  Range (min … max):    7.084 s …  7.268 s    10 runs

Then added this to ash/Cargo.toml:

[hints]
mostly-unused = true

And re-ran the benchmark together with -Zprofile-hint-mostly-unused flag:

hyperfine -s 'cargo +nightly b -p ash-examples -Zprofile-hint-mostly-unused' -p 'cargo clean -p ash' 'cargo +nightly b -p ash-examples -Zprofile-hint-mostly-unused'
Benchmark 1: cargo +nightly b -p ash-examples -Zprofile-hint-mostly-unused
  Time (mean ± σ):      6.591 s ±  0.087 s    [User: 6.030 s, System: 0.936 s]
  Range (min … max):    6.466 s …  6.731 s    10 runs

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:

hyperfine -p 'cargo clean' 'cargo +nightly b -p ash'
Benchmark 1: cargo +nightly b -p ash
  Time (mean ± σ):      6.860 s ±  0.081 s    [User: 7.038 s, System: 0.860 s]
  Range (min … max):    6.722 s …  6.994 s    10 runs

And with [hints] mostly-unused = true:

hyperfine -p 'cargo clean' 'cargo +nightly b -p ash -Zprofile-hint-mostly-unused'
Benchmark 1: cargo +nightly b -p ash -Zprofile-hint-mostly-unused
  Time (mean ± σ):      6.287 s ±  0.088 s    [User: 5.828 s, System: 0.519 s]
  Range (min … max):    6.165 s …  6.427 s    10 runs

That's the same ±600ms improvement.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-profilesArea: profilesC-tracking-issueCategory: A tracking issue for something unstable.

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @omid@epage@joshtriplett@Arnavion@MarijnS95

        Issue actions

          Tracking Issue for profile-hint-mostly-unused · Issue #15644 · rust-lang/cargo