# AI 开发之电脑性能开销优化 · Rust 篇

## Rust：别让多 worktree 各编一遍

AI 并行开发最贵的一笔开销，常常不是模型，是 **Rust 反复重编依赖**。

> **现场**：一台 8 核 Mac，两个 worktree 同时 `cargo test`。问题不在"两个 cargo"，在**每个 cargo 默认按逻辑核数拉编译器**——十几个 `rustc` 一起上，机器开始疯狂换页（swap），编译本身没挂，但电脑已经没法正常办公。

四招，都要做。

### 1. 限并发：两个轴，缺一不可

大多数人只限了一半——只限"同时几个 cargo"，忘了每个 cargo 自己还会 fan-out。

- `sem` 限**同时几个 cargo**
- [`CARGO_BUILD_JOBS`](https://doc.rust-lang.org/cargo/reference/config.html) 限**每个 cargo 拉几个 rustc**。没有它，每个 cargo 按逻辑核数并发——这才是"2 个 cargo 变 15 个 rustc"的真因。

wrapper（`heavy-cargo`）：

```sh
#!/bin/sh
# 8核/16GB：同一时间一个重型 cargo，每个 cargo 最多两个 rustc。
# 按 swap 调，别只看核数；32GB+ 可以试 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` 降低 CPU 优先级；`taskpolicy -b` 设 Darwin 的后台调度策略（压后台任务的 CPU/I-O）。两者**不严格等价** Linux 的 `ionice`，只是同一目的的平台手段。

### 2. 共享编译缓存（sccache）

[sccache](https://github.com/mozilla/sccache) 让不同 worktree 复用编译产物。关键是 incremental：

- `.cargo/config.toml` 里 `[env] CARGO_INCREMENTAL = "0"` **不生效**——`[env]` 只把变量传给 cargo 启动的子进程，来不及影响 cargo 自己的增量决策。
- 但**启动前**设 `CARGO_INCREMENTAL=0 cargo …` 有效（上面 wrapper 就是这么干的）。好处：把"关 incremental"限定在重型构建，其他项目照常增量编译，不必全局牺牲。想全局关也行，用 [`[build] incremental = false`](https://doc.rust-lang.org/cargo/reference/config.html)。

跨 worktree 命中的主要是**第三方依赖**（同一 registry、路径一致）。自有 crate **默认**因绝对路径进了缓存键而不跨 worktree 命中——但新版 sccache 的 `SCCACHE_BASEDIRS` 能归一化不同 checkout 的路径：

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

别承诺 100% 命中：`bin`、`dylib`、`cdylib`、`proc-macro` 这些要调链接器的 crate 本来就不能缓存。

**务必验证真的生效**，否则配了也不知道有没有用：

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

### 3. 各自独立 target，别共用

别为省空间把多个 worktree 指到同一个 `CARGO_TARGET_DIR`——会锁竞争，反而更慢。**复用靠缓存，不靠共享 target。**

### 4. 还想再快（按平台验证）

- **链接器**：Linux 可试 [mold](https://github.com/rui314/mold) / lld（链接阶段常吃掉一半时间）；**macOS 不要直接套 mold**——mold 的 Rust 配置明确限 `target_os = "linux"`，README 里的 Apple M1 测试跑的是 Fedora Asahi，不是 macOS。换链接器必须按目标平台单独验证。
- [cargo-nextest](https://nexte.st/) 跑测试；dev profile 里 `debug = "line-tables-only"` 砍调试信息体积。

### 最后：把约束钉进 AGENTS.md

工具装好了，agent 照样裸 `cargo test`，限流就等于没落地。写死一条：

```text
重型 Rust build/test 必须通过 heavy-cargo；
agent 不得直接并发启动多个 cargo test。
```

一句话：**限并发（两个轴）、共享缓存、隔离 target、按平台选链接器**——再把规则钉进 `AGENTS.md`，AI 让你同时开三条线，电脑才扛得住。
