コンテンツにスキップ

2026 年の高速ビルドツールチェーン: sccache、mold、nextest、そして待つことのコスト

· 13 min read · default
developmentperformancerustbuild-toolsciproductivity

待つことに関するよく知られた観察があります: 10 秒未満で、焦点が続きます。1 分を超え、コンテキストを切り替え、読んでいた糸を失います。ビルド時間はちょうどその危険な範囲に座ります。90 秒のコンパイル は単に 90 秒を費やしません — それは切り替えたタブから戻ったときに、あなたが持っていた全体を再ロードのコスト。チーム全体で 50 ビルド/日に掛ける、そして遅いビルドは不便であることを止めて、動作の形成を開始します: より大きい、より危険なコミット (反復が高価のため)、より少ないリファクタリング (フィードバックループが罰するため)、そしてローカルでスキップテスト (それらが時間がかかるため)。

2026 年ビルド パフォーマンスについての心強いことは、最大ウィンしばしばエンジニアリング ではなく構成。あなたのコードベースを再構築する必要はありません; 時間が実際に行く 3 つの異なるフェーズを対処いくつかのツールをインストール。このガイドはそれらのフェーズ — コンパイル、リンク、テスト — sccachemold、および cargo-nextest を通じてカバーし、bacon をインナー ループとして、そして重要に、そのいずれかが役に立つかどうかを測定する方法。

最適化前に測定

単一の最も一般的な間違いは、間違ったフェーズを最適化。「ビルドが遅い」診断ではなく — ビルドは最小コンパイル、リンク、(実行している場合) テスト、そしてプロジェクト別バランスは非常に異なります。多数の小クレートと巨大ファイナルバイナリ持つコードベースはそのほとんどをリンク時に費やしてもよい; 重いジェネリクスとマクロ付きはコンパイルによって支配されてもよい; 成熟プロジェクトはテストにより多くを費やしてもよい両方で。

だからタイミング分解により始めるのではなく推測。Rust で、cargo build --timings 各クレートにどのくらい時間がかかったかを正確に示す HTML レポートを生成し、並列化の停止頻度 — しばしば 1 つの依存性がすべてを連続化させたことを明らかにするか。より粗いビューに、time cargo build クリーン ツリーで vs インクリメンタルコールド構築にいくら支払うかが告知。そして hyperfine は単一ノイジー実行ではなく統計的に健全な前/後比較を与えます。

この matters 各ツール以下は 1 つのフェーズに対処するため、他のため何もしません。あなたのボトルネックがコンパイルの場合に高速リンカーをインストールすると丸め誤りを生成し、進歩の誤感覚を与えます。

コンパイル: 既に構築したものを再構築を停止

コンパイル内での無駄の最一般的なソースは冗長性 — 同じ依存性クレート、同じフラグで構築、あなたまたは同僚またはある同僚が 1 時間前に構築した CI ランナー。sccache これを直接対処: コンパイラをラップ、入力をハッシュ、そしてキャッシュされたアーティファクトを返す時の正確なコンパイル見た。これは Rust、C/C++、および CUDA をサポート。

sccache をローカル キャッシュを超える昇格させるものは共有ストレージ バックエンド — S3、GCS、Redis、または GitHub Actions キャッシュ。これが CI の経済学を変えます。デフォルト CI 経験はすべての依存性をスクラッチから構築するため、コンパイル冷たいマシンです。これは純粋な無駄です。それらの依存性は変わっていません。共有キャッシュと、最初の実行が入力し、その後のすべての実行がダウンロード代わりのコンパイル。チーム一般的に CI ビルド時間 を半分以上、同じキャッシュが開発者マシンを提供に見ます。

セットアップが環境変数 (RUSTC_WRAPPER=sccache) またはに ~/.cargo/config.toml エントリ。重要なフォローアップは検証: sccache --show-stats ヒット レートをレポートし、レート数値は何かが入力を変わっています — 不安定な RUSTFLAGS、絶対パスが出力にベイク、またはインクリメンタルコンパイル干渉の信号。ローカル キャッシュ何もないより悪い低いヒット レート。ルックアップコストを支払うため。

リンク: 連続化テール

リンク人員が見落とす、それはしばしば編集・コンパイル・実行ループで最も悪いことです。理由: コンパイルはコア全体で並列美しく、しかしリンク従来そうではない。2 百ファイルを 16 コア間でコンパイル 20 秒で、次に 1 つのコアがリンク際 8 秒待つ。インクリメンタル再構築で — あなたが 1 つのファイル変えた唯一のリコンパイルだけ — リンクは最もあなたの待機。

mold は最初から利用可能なすべてのコアを使用するため設計したドロップイン リンカーです。それはルーチンで 1 つの桁によってリンク時間をカット、そしてウィンはインクリメンタル再構築パスにはまりのため、それはデベロッパーが感じる最もすぐに。採用は正直に些細です: mold -run cargo build は設定なしでビルドコマンドをラップ、またはあなたはリンカー フラグに永続的設定に -fuse-ld=mold を追加。

mold を sccache と組み合わせる理由は、彼らは同じ待機のの異なる半をアタック。sccache があなたが構築したコンパイル排除またはシステム CI; mold キャッシュできてない残るリンクを高速化。どちらかが他を代用; ともたちは通常 ともだけより大きい改善を生成。

テスト: 分離と正直な障害

3 番目のフェーズはテスト、そして cargo-nextest スピード だけではなく模型を変える。標準的なcargo test バイナリ内の 1 つのプロセス内ですべてのテストを実行; nextest 各テストを独自プロセス内で実行。これは典型的な 2–3x スピードアップを超える複数の結果を得ます。

分離は実になるになります。 テストは交互にグローバル状態を破壊できないため、順序依存障害表面すぐに代わりに神秘的に 数ヶ月後に表示される代わりに。クラッシュ帰属可能です — テスト segfault またはアボート、バイナリの結果がその 1 つを学べます。フレーキーテストが名前ずけられた: --retries では、失敗次が合格するテストはFLAKY としてレポートされ、ほぼ合格後に再実行、これが重要 フレーキーテストが異なる問題である、そして隠すことは、それはスイートが腐るときだ。とは CI シャーディング組み込み --partition 経由、ですから、実行全体にスイート分割は既存のプロジェクトではなく、フラグ。

知る主要なギャップ: nextest doctest を実行しないため、一般的な CI パターンは cargo nextest run && cargo test --doc

インナーループ: ビルドを手動で実行しない

最速ビルドは実行する必要がないもの。bacon サイドターミナルで実行、ソースを見守り、そしてすべての保存時に cargo check、clippy、またはテストの再実行、コンパクト常に最新エラー概要を表示。利得は生スピード — それはコンパイル思考と重なる代わりビルド ブロック、そしてあなたは出力にスクロール代わりのエラーを最初に見えます。

フェーズツール通常こちら自然に配列: bacon が継続的フィードバック与える、sccache と mold は各バックグラウンド実行を十分高速に、前エラー読み終わる前に終了します。非 Rust プロジェクトに、watchexec あらゆるコマンドに同じ継続的フィードバックパターンを提供。

それを組む、そして検証

完全なセットアップ短い:

cargo install sccache cargo-nextest bacon --locked
sudo apt install mold        # または brew install mold
# ~/.cargo/config.toml
[build]
rustc-wrapper = "sccache"

[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]

次に各ピースを独立して検証します。無言の誤構成が容易 : sccache --show-stats 昇る ヒット レート表示すべき; readelf -p .comment ./target/debug/yourbin | grep -i mold 実際に mold リンク確認; cargo nextest run cargo test より視認性に速く終了すべき。cargo build --timings での現実的な変更 — 1 つのファイルを接触、リビルド — 全体結果を測定、それをクリーン構築ではなく。インクリメンタル再構築は 1 日中、あなたが実際にやること。

CI、共有キャッシュバックエンドを追加 (SCCACHE_GHA_ENABLED=true GitHub Actions 、または S3 バケットで) と nextest の --partition を実行者全体にシャード。CI がこれらのツールが最も劇的に支払いのため、機械がデフォルトが冷たくそれは毎回実行で同じ無駄な仕事を繰り返すため。

を超えて設定: 実際は何がビルドを遅くする

あなたが位相ツールが 適用され、ループがまだ痛い場合、残りの原因は構造的 — そして理解する価値があっても、それらに動作することに決定、理由が一部プロジェクトはほぼ最適化に抵抗するかを説明するため。

依存性数と深さ 最一般的。すべてのクレート依存症は少なくて一度コンパイルする必要があり、深い依存グラフは連続化: クレート C はB が終わるまで開始できず、それは A を待ちました。cargo build --timings はこれを 長い臨界パスとアイドル コアとして直接示します。依存性は使用するあなたをすべきが審査 — 1 つのヘルパー関数のため大規模クレートを引き進める — しばしば最高レバレッジ構造修正、供給チェーン面を同時に削減。

ジェネリックとマクロ重いコード インスタンス化に比例してコンパイル時間コスト。ジェネリック関数は 20 のタイプで使用される 20 回コンパイルされ、重いプロシージャマクロコンパイル時間で任意のコード実行。ホット ジェネリックが汎用必要がない、単形化が手動またはその境界を狭めることで測定可能なコンパイル時間をカット。これは人間工学との対する真の取引のため、計測前に身をかがむ必要はありません。

クレート粒度 は両方に切ります。1 つの巨大クレート不可能内部並列化しており小編集のための完全再構築を強い。百のたくさんの小さいクレートはクレート毎オーバーヘッドを追加し、より深い依存チェーン。有用なヒューリステックはレートを分割することをボーダーの変わり —安定な基礎的コード独自クレートのため、編集が不安定なコード再構築しません。

デバッグ情報と最適化設定 が最廉価な構造レバー。完全なデバッグ情報は生成と結べるコスト; debug = 1 (ライン テーブルのみ) は多くの場合、バックトレースに十分費用の一部。そして依存性をステップしない、opt-level オーバーライドがプロファイルをさせあなたのコード自分のすべてコンパイルを支払わずに最適化します。

これ configuration 変更どれもない、このリストにある理由です。しかし プロジェクト キャッシングと高速リンカーに遅れても、答えはほぼ常にこのリストにあります。

停止するときを知る

閉じ警告: ビルド最適化は自体のタスク減る戻りとは、感じ生産的であることに異常に良い。インクリメンタル再構築が数秒になったら、より詳しい調整は小をバイ、そして残りレバーはプログレッシブより侵襲 — クレート境界を再構築、依存性の切り、ジェネリクスをリソース。それらことがあります。する価値その彼らはエンジニアリング ビッグダメージで実リスク構成な変更ではないに対する。

正直なシーケンスは: 測定最初、適用安価フェーズ固有修正 (キャッシュ、リンカー、テスト ランナー)、測定再度、そして停止ループ最のもはやあなたの意識を破りません。目標は決してベンチマーク数 — それはあなたが思考仕上る長さフローにいるように停止させるあなたが保存撃つのは、集中を保つ。

ボトムライン

遅いビルドは変更行動、スケジュールだけ、そして 2026 年で最大修正は構成ではなくエンジニアリング。診断どの位相実際に費やす — cargo build --timingshyperfine は直感をビルド —次に適用ツール対処: sccache あなたまたは CI が既に構築しものを再構築すること停止、mold インクリメンタル再構築を支配する連続化リンク並列化、cargo-nextest より高速は、分離して、フレーキー意識テスト組み込み CI シャード、そして bacon コンパイルが発生するための思考あなたが間待つ代わりに。本物各 1 つにリアル従事、共有キャッシュで CI を使用そこで無駄が最大で、最適化停止ひとたびループ停止あなたをさ中断。

参照とリソース

ツール

背景と分析

関連 1337skills チートシート