-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
fix(resolver): share conflict cache between activation retries #14692
Conversation
r? Eh2406 |
To double check my understanding, the slowdown is only relevant if you don't have a lockfile because wee prefetch deps in a lockfile? |
Yes, when a lockfile is present the resolve takes only a few milliseconds. |
This is a delightfully small diff. The argument for correctness is kind of suttle. But now that we have talked it over @bors r+ |
☀️ Test successful - checks-actions |
Update cargo 14 commits in 15fbd2f607d4defc87053b8b76bf5038f2483cf4..8c30ce53688e25f7e9d860b33cc914fb2957ca9a 2024-10-08 21:08:11 +0000 to 2024-10-15 16:43:16 +0000 - docs: More information on what is and isn't included by cargo package (rust-lang/cargo#14684) - fix(resolver): share conflict cache between activation retries (rust-lang/cargo#14692) - fix(git): dont fetch tags by default (rust-lang/cargo#14688) - Support package selection options like `--exclude` in `cargo publish` (rust-lang/cargo#14659) - docs: install options -> uninstall options (rust-lang/cargo#14682) - docs: tools should only interpret a line starting with `{` as JSON (rust-lang/cargo#14677) - cargo test --help: clarify --tests and --benches (rust-lang/cargo#14675) - docs(env): minor improvements in environment variables doc (rust-lang/cargo#14676) - docs: document official external commands (rust-lang/cargo#14669) - Fix panic when running cargo tree on a package with a cross compiled bindep (rust-lang/cargo#14593) - Remove the support for `Cargo.toml` of the cargo-script (rust-lang/cargo#14670) - docs(resolver): Lay groundwork for documenting MSRV-aware logic (rust-lang/cargo#14662) - chore(deps): update rust crate pulldown-cmark to 0.12.0 (rust-lang/cargo#14668) - Improve resolver speed (rust-lang/cargo#14663)
Update cargo 14 commits in 15fbd2f607d4defc87053b8b76bf5038f2483cf4..8c30ce53688e25f7e9d860b33cc914fb2957ca9a 2024-10-08 21:08:11 +0000 to 2024-10-15 16:43:16 +0000 - docs: More information on what is and isn't included by cargo package (rust-lang/cargo#14684) - fix(resolver): share conflict cache between activation retries (rust-lang/cargo#14692) - fix(git): dont fetch tags by default (rust-lang/cargo#14688) - Support package selection options like `--exclude` in `cargo publish` (rust-lang/cargo#14659) - docs: install options -> uninstall options (rust-lang/cargo#14682) - docs: tools should only interpret a line starting with `{` as JSON (rust-lang/cargo#14677) - cargo test --help: clarify --tests and --benches (rust-lang/cargo#14675) - docs(env): minor improvements in environment variables doc (rust-lang/cargo#14676) - docs: document official external commands (rust-lang/cargo#14669) - Fix panic when running cargo tree on a package with a cross compiled bindep (rust-lang/cargo#14593) - Remove the support for `Cargo.toml` of the cargo-script (rust-lang/cargo#14670) - docs(resolver): Lay groundwork for documenting MSRV-aware logic (rust-lang/cargo#14662) - chore(deps): update rust crate pulldown-cmark to 0.12.0 (rust-lang/cargo#14668) - Improve resolver speed (rust-lang/cargo#14663)
What does this PR try to resolve?
Found in Eh2406/pubgrub-crates-benchmark#6.
Currently the resolve is done in a loop, restarting if there are pending dependencies which are not yet fetched, and recreating the conflict cache at each iteration.
This means we do a lot of duplicate work, especially if the newly fetched dependencies has zero or few dependencies which doesn't conflict.
This also means that the maximum depth of the dependency graph has a big impact on the total resolving time, since adding a dependency not yet seen means we will restart the resolve at the next iteration.
Here is the output of the resolve for the master branch using
solana-core = "=1.2.18"
inCargo.toml
, printing the duration from the start after each iteration:To improve the situation, this PR moves the conflict cache outside the activation loop so it can be reused for all iterations.
This is possible since when using an online registry, dependencies which are not yet fetched are not added to the candidate summary:
cargo/src/cargo/core/resolver/dep_cache.rs
Lines 248 to 266 in 82c489f
On the other hand, if a dependency query returns
Poll::Ready
, then all compatible summaries are returned, so we cannot have a partial view where only some compatible summaries would be returned. This means we cannot add a conflict in the cache which would be incompatible with future fetches, and therefore the conflict cache can be shared.Here is the output of the resolve with this PR:
Besides the huge performance savings between iterations, sharing the conflict cache has the side effect of eliminating dead paths earlier in the resolve after a restart. We can see that the duration of all iterations using this PR is less than the duration of the last iteration on master, and that it needs to resolve less dependencies overall.