# Optimizing Computer Performance Overhead in AI Development · Rust Edition

## Rust: Don’t Let Multiple Worktrees Each Compile Everything Once

The biggest cost in parallel AI development is often not the model, but **Rust repeatedly recompiling dependencies**.

> **Scene**: An 8-core Mac, two worktrees running `cargo test` at the same time. The problem is not “two cargo processes”; it is that **each cargo process defaults to spawning compilers based on the number of logical cores**. A dozen-plus `rustc` processes kick off together, the machine starts swapping like crazy, the compilation itself does not fail, but the computer is no longer usable for normal work.

Four moves. Do all of them.

### 1. Limit Concurrency: Two Axes, Both Required

Most people only limit half of it: they limit “how many cargo processes run at once” and forget that each cargo process can still fan out on its own.

- `sem` limits **how many cargo processes run at the same time**
- [`CARGO_BUILD_JOBS`](https://doc.rust-lang.org/cargo/reference/config.html) limits **how many rustc processes each cargo process spawns**. Without it, each cargo process runs with concurrency based on the number of logical cores — this is the real reason “2 cargo processes become 15 rustc processes.”

Wrapper (`heavy-cargo`):

```sh
#!/bin/sh
# 8 cores / 16GB: one heavy cargo at a time, each cargo with at most two rustc processes.
# Tune based on swap, not just core count; with 32GB+, you can try sem -j 2.
exec sem --id rust-heavy -j 1 --fg -- \
  env RUSTC_WRAPPER=sccache CARGO_INCREMENTAL=0 CARGO_BUILD_JOBS=2 \
  nice -n 15 taskpolicy -b cargo "$@"
```

`nice` lowers CPU priority; `taskpolicy -b` sets Darwin’s background scheduling policy, throttling CPU/I/O for background tasks. The two are **not strictly equivalent** to Linux `ionice`; they are just platform-specific means toward the same goal.

### 2. Share the Compilation Cache (sccache)

[sccache](https://github.com/mozilla/sccache) lets different worktrees reuse compilation artifacts. The key detail is incremental compilation:

- Setting `[env] CARGO_INCREMENTAL = "0"` in `.cargo/config.toml` **does not work** — `[env]` only passes variables to subprocesses started by cargo, which is too late to affect cargo’s own incremental compilation decisions.
- But setting `CARGO_INCREMENTAL=0 cargo …` **before startup** does work; the wrapper above does exactly that. The benefit: disabling incremental compilation is limited to heavy builds, while other projects can keep using incremental compilation as usual. No global sacrifice required. If you do want to disable it globally, use [`[build] incremental = false`](https://doc.rust-lang.org/cargo/reference/config.html).

Across worktrees, cache hits mainly come from **third-party dependencies** with the same registry and consistent paths. Your own crates **by default** will not hit across worktrees because absolute paths are part of the cache key — but newer sccache versions provide `SCCACHE_BASEDIRS`, which can normalize paths across different checkouts:

```sh
SCCACHE_BASEDIRS="$PWD" RUSTC_WRAPPER=sccache CARGO_INCREMENTAL=0 cargo check
```

Do not promise 100% hits: crates such as `bin`, `dylib`, `cdylib`, and `proc-macro` invoke the linker and cannot be cached in the first place.

**Always verify that it is actually working**; otherwise, you will not know whether your setup is doing anything:

```sh
sccache --zero-stats
heavy-cargo test -p server
sccache --show-stats     # Check cache hits / requests executed
```

### 3. Keep Each target Directory Separate; Do Not Share Them

Do not point multiple worktrees at the same `CARGO_TARGET_DIR` to save space — that creates lock contention and can make things slower. **Reuse should come from the cache, not from a shared target directory.**

### 4. Want Even More Speed? Validate Per Platform

- **Linker**: On Linux, you can try [mold](https://github.com/rui314/mold) / lld; the linking phase often eats half the time. **Do not apply mold directly on macOS** — mold’s Rust configuration explicitly limits it to `target_os = "linux"`, and the Apple M1 test in the README runs Fedora Asahi, not macOS. Any linker change must be validated separately for the target platform.
- Use [cargo-nextest](https://nexte.st/) to run tests; set `debug = "line-tables-only"` in the dev profile to reduce debug info size.

### Finally: Pin the Constraints in AGENTS.md

If the tools are installed but the agent still runs bare `cargo test`, your throttling has not actually landed. Write one rule explicitly:

```text
Heavy Rust build/test must go through heavy-cargo;
agents must not directly start multiple cargo test processes concurrently.
```

In one sentence: **limit concurrency across two axes, share caches, isolate target directories, and choose linkers per platform** — then pin the rules in `AGENTS.md`. Only then can AI let you keep three lines of work open at once without crushing your computer.
