rustfmt: cargo fmt --all is slow in a workspace project
Problem
cargo fmt --all runs unexpectedly slow in a medium-sized workspace project.
Steps
- Run a GitHub workflow that runs
cargo fmt --allon the repository. - Check execution time.
This run shows rustfmt and/or cargo pausing for more than 20 s before producing any output in verbose mode. Seen with timestamps in the raw log:
2020-06-08T17:05:32.3268959Z [command]/usr/share/rust/.cargo/bin/cargo fmt --all --verbose -- --check --verbose
2020-06-08T17:05:55.8733086Z [bench (2018)] "/home/runner/work/chain-libs/chain-libs/btree/benches/benchmark.rs"
Notes
Output of cargo version:
cargo 1.44.0 (05d080faa 2020-05-06)
Output of rustfmt --version
rustfmt 1.4.14-stable (e417356 2020-04-21)
Virtual environment information from GitHub workflow: Operating System Ubuntu 18.04.4 LTS Virtual Environment Environment: ubuntu-18.04 Version: 20200518.1 Included Software: https://github.com/actions/virtual-environments/blob/ubuntu18/20200518.1/images/linux/Ubuntu1804-README.md
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 25 (20 by maintainers)
Commits related to this issue
- Don't use --all flag with cargo fmt It adds nothing useful to this project and furthermore, slows down the test run. Per suggestion in https://github.com/rust-lang/rustfmt/issues/4247#issuecomment-64... — committed to input-output-hk/chain-libs by deleted user 4 years ago
- Don't use --all flag with cargo fmt It adds nothing useful: cargo fmt checks all legitimate workspace members, and for the chain-deps we have a CI workflow in its own reposotiry. Moreover, the --all ... — committed to input-output-hk/jormungandr by deleted user 4 years ago
- Don't use --all flag with cargo fmt It adds nothing useful to this project and furthermore, slows down the test run. Per suggestion in https://github.com/rust-lang/rustfmt/issues/4247#issuecomment-64... — committed to input-output-hk/chain-libs by deleted user 4 years ago
- Auto merge of #8994 - jonhoo:manifest-in-local-deps-meta, r=ehuss metadata: Supply local path for path dependencies This is potentially a simpler way to address #7483 than #8988. /cc https://github... — committed to rust-lang/cargo by bors 3 years ago
- Don't use --all flag with cargo fmt This slows down the job considerably with no added benefit, see https://github.com/rust-lang/rustfmt/issues/4247#issuecomment-641484560 — committed to input-output-hk/vit-servicing-station by deleted user 3 years ago
- Merge branch 'cargo-fmt-faster' into 'master' Run `cargo fmt` without `--all` According to [this thread](https://github.com/rust-lang/rustfmt/issues/4247), the `--all` flag causes `cargo-fmt` to cal... — committed to dfinity/ic by deleted user 2 years ago
@jonhoo - stretched rather thin and having to juggle 20 different things. This is on the top of my list for whenever I get a chance to actually work on some rustfmt development, but right now my limited rustfmt bandwidth is preoccupied with other general support and maintenance activities.
I also want to stress that there is no either/or here. We’re definitely going to make this change, and there’s a good chance we’ll probably go forward with #4722 as well.
However, really important to note that #4722 would only be at play with explicit workspaces, but if you have an explicit workspace you do not need to use
--allanyway (unless you just really want to format your entire workspace by executing the command from within one of your subdirectories). If you’ve not set up an explicit workspace, but instead have just structured your project with relative path depdencies between your packages (e.g. like Clippy or RLS), then you do need--alland #4722 has 0 impact on that use case.I think the main issue here is the disconnect between what the
--allflag means and when it’s actually needed withcargo fmtvs. what folks, understandbly but often incorrectly, assume based on what--allmeant previously with other cargo subcommands. (Refs https://github.com/rust-lang/rustfmt/issues/3911)Background
There’s only a few use cases I recall where the
--allflag withcargo fmtis currently helpful/meaningful:cargo fmtin a subdirectory of an explicit workspace where you want to run formatting commands against the entire workspace/all the explicit workspace members (all members are formatted by default when running from the root of an explicit workspace)cargo fmtin the root directory of an implicit workspace where you want to run formatting commands against all implicit workspace memberscargo fmtagainst a given package which has one more local/path based dependencies where you want to run the formatting commands against the current package and that local/path based package (as well as any local/path based deps that package may have, recursively).I suspect that the majority of instances where folks are using the
--allflag withcargo fmtfalls into those first two buckets, while the third is relatively more of an edge case.cargo fmtcurrently leverages thecargo metadatacommand in order to discover the workspace information which is then used to construct the correspondingrustfmtcommands;cargo fmtdoes not directly parse Cargo.toml files.Accordingly, in order to support the second (and third) use case,
cargo fmt --allrunscargo metadatawithout the--no-depsflag (due to https://github.com/rust-lang/cargo/issues/7483) to ensure that thecargo metadataoutput contains the information thatcargo fmtneeds in order to properly locate and format those implicit workspace members/path-based dependencies.AIUI, running
cargo metadatawithout the--no-depsflag results in the registry index hit that is presumably the cause of the increased run time folks are seeing which is probably rather apparent in CI-type environments.Next Steps
We’ve tried updating the help text for the
--allflag though that certainly hasn’t solved the disconnect, and I believe we probably need to take additional action to try to ameliorate the confusion.Perhaps some non-mutually exlusive actions we could consider:
cargo fmtdocumentation to try to provide better guidance on when--allis required vs. when it should likely be avoided.cargo metadataand work on addressing https://github.com/rust-lang/cargo/issues/7483cargo metadatato get workspace information (parse Cargo.toml files directly, etc.)cargo fmtflags and/or add new flags (this would almost certainly result in a breaking change that’d require a major version bump). For example, we could add a--workspaceor even--explicit-workspace) flag that would support the first use case (explicit workspaces) and use--all, or even rename/replace it with--implicit-workspaceto support the second and third use caseThe resolution for this will be in the next release. Purely anecdotal data points on my slow machine so treat them as such, but suffice to say that folks using
--allshould notice some marked performance improvements. I’m observing execution time going from multiple minutes down to 1-2 seconds in an uncached/clean environment, and from 30 seconds down to that same 1-2 seconds in a cached/dev laptop type env.Available on nightly as of
2021-10-24(perhaps the day before), slated to land on stable as part of v1.58Thanks @jonhoo, planning on looking at it this week
Won’t commit to any target timeframe just yet, especially given the holidays, but yes will try to get this out soon once possible to proceed. Unfortunately due the various non-rustup channels through which rustfmt is distributed and can be used there will be a bit of extra complexity to handle working with older versions of cargo that may not the newer changes.
I’m also not sure if the cargo_metadata crate will need to first be updated as well before we can start taking advantage of https://github.com/rust-lang/cargo/pull/8994