Skip to content
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

Optimization: parse manifest only once #2898

Merged
merged 1 commit into from
Nov 12, 2021

Conversation

mkeeter
Copy link
Contributor

@mkeeter mkeeter commented Nov 10, 2021

I was building a project which invoked cargo multiple times, and noticed that a no-op build (i.e. a build with no local changes) was surprisingly slow.

Generating a flamegraph of one cargo call, I noticed the following:

Screen Shot 2021-11-10 at 1 40 11 PM

About half the work is done in Manifestation::load_manifest, which is called twice to parse the same 700K TOML file (here and here).

This PR adds a new struct in toolchain.rs which encapsulates this parsed manifest plus other relevant data. This struct is then used in config.rs to eliminate the double-parsing.

I also use this struct to clean up duplicate code in toolchain.rs, e.g. this comment:

// Overlapping code with get_manifest :/.

I see a 15-25% speedup in a no-op build, depending on the project!

  • Tests all pass (at least on my machine!)
  • No new clippy lints (there are a few pre-existing lints in areas I haven't touched)
  • rustfmt run

@kinnison
Copy link
Contributor

You have reached a similar conclusion to that which led me in #2626 to think about writing #2627.

My gut feeling is that it'd be best to rewrite the toml into something which can be parsed more quickly, rather than complicating the internal pathways in rustup regarding parsed toolchain manifests.

I will have a read through your change, but I'm sceptical that as-is it'll be the right answer.

I am grateful for the drive-by cleanup work though, that idea is excellent.

Copy link
Contributor

@kinnison kinnison left a comment

Choose a reason for hiding this comment

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

I take back my comment, I think the extra complication of that struct is simple enough that I do not object to it. This looks very worthwhile to include, thank you!

Could you please deal with the one comment I made on the code; and then when you're done, rebase the changes together, since I prefer to not merge "run rustfmt" type patches into the code if I can avoid it.

Thank you again.

src/toolchain.rs Outdated
pub(crate) struct ToolchainDescWithManifest {
toolchain: ToolchainDesc,
manifestation: Manifestation,
pub(crate) manifest: Manifest,
Copy link
Contributor

Choose a reason for hiding this comment

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

With the struct being pub(crate) there's no need for the (crate) modifier on this field.

This adds an intermediate struct which includes a parsed manifest, and
eliminates a bunch of duplicated code.  Only parsing the manifest once
speeds up `find_or_install_override_toolchain_or_default` by about 50%
which is the critical path for a rebuild with no changes.

There's also a drive-by fix for running test on macOS aarch64.
@mkeeter mkeeter force-pushed the parse-manifest-only-once branch from 6fba61f to 9e945ed Compare November 11, 2021 14:09
@mkeeter
Copy link
Contributor Author

mkeeter commented Nov 11, 2021

Cool – I made that one change, then squashed into a single commit and force-pushed it, so we should be good to go!

@rbtcollins rbtcollins merged commit 1218285 into rust-lang:master Nov 12, 2021
@mkeeter mkeeter deleted the parse-manifest-only-once branch July 12, 2022 13:55
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.

3 participants