add a cache for discovered workspace roots#10776
Conversation
This centralizes the workspace discovery code into one location `find_workspace_root_with_loader` so that it isn't duplicated.
|
r? @ehuss (rust-highfive has picked a reviewer for you, use r? to override) |
weihanglo
left a comment
There was a problem hiding this comment.
Seems reasonable to me. Just a few questions:
- Do we need to document how the result would be cached, as it affects some public API?
- Is there a chance that there is a long-running cargo API consumer getting outdated caches? Should be really rare edge case I guess.
c719971 to
fd8bcf9
Compare
I'm not sure that this affects any public API to my knowledge. It should just make it so we don't parse a workspace root twice if it has not been loaded yet into a list of workspace packages or when we do not have access to the list of workspace packages.
This shouldn't be a problem unless there is an edit to a workspace root manifest while cargo is running. If there is an edit while cargo is running, I think it is best to have the edit appear when cargo is run next either way. |
weihanglo
left a comment
There was a problem hiding this comment.
unless there is an edit to a workspace root manifest while cargo is running
That's exact what I meant. Anyway, I am going to merge this. The benchmark result on my machine is as great as yours. And we can always add docs later if needed.
|
@bors r+ Thanks for the PR! |
|
📌 Commit fd8bcf9 has been approved by |
|
☀️ Test successful - checks-actions |
…79e13a071ad4b17435bd6bfa4c 2022-07-03 13:41:11 +0000 to 2022-07-09 14:48:50 +0000 - Mention `[patch]` config in "Overriding Dependencies" (rust-lang/cargo#10836) - Update terminal-width flag. (rust-lang/cargo#10833) - Refactor check_yanked to avoid some duplication (rust-lang/cargo#10835) - Fix publishing to crates.io with -Z sparse-registry (rust-lang/cargo#10831) - Make `is_yanked` return `Poll<>` (rust-lang/cargo#10830) - Fix corrupted git checkout recovery. (rust-lang/cargo#10829) - add a cache for discovered workspace roots (rust-lang/cargo#10776)
Update cargo 7 commits in c0bbd42ce5e83fe2a93e817c3f9b955492d3130a..b1dd22e668af5279e13a071ad4b17435bd6bfa4c 2022-07-03 13:41:11 +0000 to 2022-07-09 14:48:50 +0000 - Mention `[patch]` config in "Overriding Dependencies" (rust-lang/cargo#10836) - Update terminal-width flag. (rust-lang/cargo#10833) - Refactor check_yanked to avoid some duplication (rust-lang/cargo#10835) - Fix publishing to crates.io with -Z sparse-registry (rust-lang/cargo#10831) - Make `is_yanked` return `Poll<>` (rust-lang/cargo#10830) - Fix corrupted git checkout recovery. (rust-lang/cargo#10829) - add a cache for discovered workspace roots (rust-lang/cargo#10776)
Fix nested workspace resolution This fixes a bug that was introduced in #10776 with nested workspaces. As an example, say we have two workspaces: `/code/example/Cargo.toml` and `/code/example/sub/Cargo.toml`, and a crate within the `sub` workspace `/code/example/sub/test-crate/Cargo.toml`. Since the `ws_roots` is a HashMap with randomized ordering, this code will _sometimes_ cause the workspace at `/code/example/Cargo.toml` to be discovered and used _before_ `/code/example/sub/Cargo.toml`, https://github.com/rust-lang/cargo/blob/b1dd22e668af5279e13a071ad4b17435bd6bfa4c/src/cargo/core/workspace.rs#L1704-L1710 This will then cause the `validate_members` method to fail as the member thinks it is a member of a different workspace than it should be. https://github.com/rust-lang/cargo/blob/b1dd22e668af5279e13a071ad4b17435bd6bfa4c/src/cargo/core/workspace.rs#L874-L891 This change just makes it so that the input manifest path is walked up to find the (presumably) most appropriate workspace so that the ordering of the `HashMap` doesn't matter. If you encounter this bug by running cargo nightly, you can workaround it by adding the crate(s) to the `excluded` field in the workspace they don't belong to.
Add a test for regressions in selecting the correct workspace root This adds a test to check for regressions in selecting the correct workspace when there are nested workspaces. #10846 solved a problem with nested workspace resolution that was caused by #10776. `@ehuss` [suggested](#10846 (comment)) that a test should be added to ensure that this issue does not pop up again. I ensured that this worked by testing against commit before #10846. Sporadically I would get an error that was the same as described in #10846. ``` error: package `{path}/cargo/target/tmp/cit/t0/foo/sub/foo/Cargo.toml` is a member of the wrong workspace expected: {path}/cargo/target/tmp/cit/t0/foo/sub/Cargo.toml actual: {path}/cargo/target/tmp/cit/t0/foo/Cargo.toml ``` I then tested it on the commit with the fix and the test passed every time. --- While this does add a test to catch any regression I am worried that it will not catch it every time. It was noted in #10846 that this error would sometimes happen but not every time, in my testing I found this to be true as well. Since this is caused by the `HashMap` order changing each run, switching to something ordered like `BTreeMap` **_should_** catch any regressions every run (if the implementation were to ever change). I'm not sure if this is necessary so I figured I would note the concern here.
History
@ehuss noticed that workspace inheritance caused a significant increase in startup times when using workspace inheritance. This brought up the creation of #10747.
When using a similar test setup to the original I got
This showed a large increase in time per cargo command when using workspace inheritance.
During the investigation of this issue, other performance concerns were found and addressed. This resulted in a drop in time across the board but heavily favored workspace inheritance.
Performance after changes
hyperfine --warmup 10 "cd rust; ../../../target/release/cargo metadata" "cd rust-ws-inherit; ../../../target/release/cargo metadata" --runs 40New Benchmark
cargo bench -- workspace_initialization/rustChanges Made
Configto hold foundWorkspaceRootConfigsWorkspaceRootConfigget added to the cache when parsing a manifestTesting Steps
To check the new benchmark:
cd benches/benchsuitecargo bench -- workspace_initialization/rustUsing
hyperfine:cargo build --releaserustandrust-ws-inheritinbenches/workspacesbenches/workspacesrustcinfo. Inrustandrust-ws-inherit, run:cargo +nightly c -p linkchecker. Otherwise it would be measuringrustcoverhead.hyperfine --warmup 10 "cd rust; ../../../target/release/cargo metadata" "cd rust-ws-inherit; ../../../target/release/cargo metadata" --runs 40closes #10747