From bb821e908e9be67cf95db3f4b1709aa7770e582f Mon Sep 17 00:00:00 2001 From: Mohamed Mansour Date: Mon, 18 May 2026 22:11:27 -0700 Subject: [PATCH] chore: stop xtask from bloating target/ and slowing the gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The local quality gate (cargo xtask check) was taking 18+ minutes on long-lived working copies, even though the actual compile + test work was only ~2 minutes. The root cause was the workspace target/ directory growing to 160+ GB / 1.1M+ files from accumulated incremental compilation state and per-feature fingerprint variants. Cargo then spent most of every subsequent invocation just stat'ing fingerprint files. Two changes: * Force `CARGO_INCREMENTAL=0` on every cargo invocation that xtask spawns. xtask never runs an inner edit-compile loop — every cargo call it makes (gate steps, examples build, bench, E2E, packaging) is one-shot, so incremental compilation just produces garbage that cargo then has to scan on the next run. CI was already immune to this via Swatinem/rust-cache@v2 (which sets the same env). Real inner-loop development with `cargo build` / `cargo test` outside xtask is unaffected. * Switch the gate's bench-validate step to `--profile=dev`. The step exists only to run criterion's `--test` smoke path, but the default bench profile inherits the release profile's `lto = true, codegen-units = 1`, so it was recompiling the entire `microsoft-webui` graph with full LTO just to assert criterion's entry point loads. Dev profile reuses unit-test artifacts and drops that step from ~44s to ~2s. Real benchmark measurements via `cargo xtask bench` still use the unchanged bench profile, so reported numbers remain accurate. Measured on a working copy where target/ had grown organically: ``` before (bloated target/, 160 GB): 18m23s after (bloated target/, 160 GB): N/A — change forces clean rebuild after (clean target/): 42s (first run) after (clean target/): 35s (subsequent runs, no growth) ``` bench-validate step alone: ``` before: ~44s (bench profile, LTO + codegen-units=1) after: ~2-3s (dev profile, reuses test artifacts) ``` Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- xtask/src/main.rs | 9 +++++++++ xtask/src/util.rs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index ee399901..db6cbabe 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -567,6 +567,14 @@ impl Step { const BENCH_VALIDATE: Self = Self { name: "bench (validate)", run: || { + // Use the dev profile (not the default bench profile) for the + // criterion `--test` smoke run. The bench profile inherits the + // release profile's `lto = true, codegen-units = 1`, which spends + // ~40s compiling the full graph just to assert criterion's + // `--test` entry point runs once. The dev profile reuses the + // already-built unit-test artifacts and finishes in seconds. Real + // benchmark measurements (via `cargo xtask bench`) continue to + // use the unchanged bench profile so their numbers stay accurate. run_command_quiet( "cargo", &[ @@ -575,6 +583,7 @@ impl Step { "microsoft-webui", "--bench", "contact_book_bench", + "--profile=dev", "--", "--test", ], diff --git a/xtask/src/util.rs b/xtask/src/util.rs index 931fc592..6b636b0b 100644 --- a/xtask/src/util.rs +++ b/xtask/src/util.rs @@ -72,7 +72,25 @@ pub fn run_command_quiet(cmd: &str, args: &[&str], cwd: Option<&Path>) -> Result /// On Windows `CreateProcessW` cannot launch `.cmd`/`.bat` scripts directly. /// This function uses `which` to resolve the executable path and, when the /// target is a shell script, wraps it in `cmd.exe /c `. +/// +/// For cargo invocations, this also forces `CARGO_INCREMENTAL=0`. xtask is +/// only used for one-shot work (gate, examples, bench, packaging, E2E) and +/// never for an inner edit-compile loop, so incremental compilation provides +/// no benefit. Leaving it on causes the workspace `target/` dir to balloon +/// (the incremental cache and per-feature fingerprint variants grow into the +/// tens of gigabytes), which then makes every subsequent cargo invocation pay +/// huge startup time scanning hundreds of thousands of stale fingerprint +/// files. Disabling it here keeps `cargo xtask check` reliably fast on +/// long-lived working copies. pub fn build_command(cmd: &str, args: &[&str]) -> Command { + let mut command = build_command_inner(cmd, args); + if cmd == "cargo" { + command.env("CARGO_INCREMENTAL", "0"); + } + command +} + +fn build_command_inner(cmd: &str, args: &[&str]) -> Command { #[cfg(windows)] { resolve_windows_command(cmd, args)