Skip to content

Use new hints.mostly-unused to speed up compilation #4208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

joshtriplett
Copy link
Contributor

Most users of the AWS SDK crates will use a fraction of their API
surface area.

Nightly rustc now provides an option -Zhint-mostly-unused to tell it
to defer as much compilation as possible, which provides a substantial
performance improvement if most of that compilation doesn't end up
happening. Cargo plumbs this option through using the new [hints]
table. This will cause users of the AWS SDK crates to default to setting
hint-mostly-unused. (Top-level crates can override this if they wish,
using a new profile option.)

Note that setting this hint does not increase the MSRV of the AWS SDK
crates, as old versions of Cargo will ignore it. New versions of Cargo
will respect it automatically (and, until we stabilize it, Cargo will do
nothing unless you pass -Zprofile-hint-mostly-unused to cargo).

Some sample performance numbers: this takes aws-sdk-ec2 compilation
time ~4m07s to ~2m04s, a ~50% speedup.

Please note that this change to the code generator is the first Kotlin code
I've ever written, and I can't seem to get gradle to run locally in order to
test it, so this is a draft. I've extensively tested the addition of the
hints table manually, but I'm currently relying on CI to verify that this
produces the expected Cargo.toml changes for the aws-sdk-* crates.

Checklist

  • For changes to the smithy-rs codegen or runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "client," "server," or both in the applies_to key.
  • For changes to the AWS SDK, generated SDK code, or SDK runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "aws-sdk-rust" in the applies_to key.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Most users of the AWS SDK crates will use a fraction of their API
surface area.

Nightly rustc now provides an option `-Zhint-mostly-unused` to tell it
to defer as much compilation as possible, which provides a substantial
performance improvement if most of that compilation doesn't end up
happening. Cargo plumbs this option through using the new `[hints]`
table. This will cause users of the AWS SDK crates to default to setting
`hint-mostly-unused`. (Top-level crates can override this if they wish,
using a new profile option.)

Note that setting this hint does not increase the MSRV of the AWS SDK
crates, as old versions of Cargo will ignore it. New versions of Cargo
will respect it automatically (and, until we stabilize it, Cargo will do
nothing unless you pass `-Zprofile-hint-mostly-unused` to cargo).

Some sample performance numbers: this takes `aws-sdk-ec2` compilation
time ~4m07s to ~2m04s, a ~50% speedup.
@joshtriplett joshtriplett marked this pull request as ready for review July 13, 2025 09:29
@joshtriplett joshtriplett requested review from a team as code owners July 13, 2025 09:29
@joshtriplett joshtriplett marked this pull request as draft July 13, 2025 09:29
Copy link
Contributor

@aajtodd aajtodd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a most welcome PR so first thank you. We've been discussing for a while now how we're going to improve compile times for the SDK crates but working on the compiler is not our area of expertise and some service models like EC2 are just large and there will only be so much we can do on our side.

Happy to help try and work through the gradle issues, relying on CI is fine as well though.

@@ -138,6 +139,7 @@ fun testRustSettings(
moduleAuthors,
moduleDescription,
moduleRepository,
hintMostlyUnused,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

order here appears off

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ought to be something like

    ...
    license,
    examplesUri,
    minimumSupportedRustVersion = null,
    hintMostlyUnused,
)

@landonxjames
Copy link
Contributor

Reading through the proposed blog post on this feature and the corresponding Zulip thread I wonder if it would be best to scope this change to just a few of our larger more compilation heavy crates to begin? The blog says:

Always do performance analysis when considering this hint, and only apply it if
it applies obvious and substantial wins for your users. Never apply it across
the board to all your dependencies.

Compilation improvements are a frequent ask from our users (see the most upvoted issue on the aws-sdk-rust repo), so this is definitely something we want, and I think the intent here applies to some of the more popular AWS crates, especially ones that combine control/data plane operations in a single client (EC2, S3, DDB). But I don't know that we would want this on all crates from the outset without a ton of benchmarking of customer applications.

Since this is such a high user priority if you don't feel like you have the comfort with Kotlin (or desire/free time to develop it) to scope this we can discuss taking over the work on our team. If you were interested in doing the work it would probably look something like a simple decorator customizing the manifest that is registered in AwsCodegenDecorator and only targets a few specific services.

@ysaito1001
Copy link
Contributor

Love the overall direction! We can definitely massage this on our end, if needed.

As Landon says, having an allow list for target services and making the list configurable through codegen settings might be desirable (like the one we used to have for event streams).

@joshtriplett
Copy link
Contributor Author

I'd be happy to see this taken over by someone familiar with both Kotlin and the code generator.

And it seems fine to scope this to just the biggest crates; it wouldn't make sense, for instance, for a crate with only a couple of functions.

@landonxjames
Copy link
Contributor

I'd be happy to see this taken over by someone familiar with both Kotlin and the code generator.

And it seems fine to scope this to just the biggest crates; it wouldn't make sense, for instance, for a crate with only a couple of functions.

Awesome, thanks for bringing this new feature to our attention. I will take over this work in a week or two when I clear out my current tasks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants