Rustコンパイル速度の「限界」を突破する:アーキテクトが教える極限ビルド最適化の解剖学
Rustのコンパイル速度が遅いと嘆くのは、ツールチェーンの「デフォルト」に甘んじている証拠だ。我々アーキテクトにとって、ビルド時間は「税金」である。放置すればCIの待ち時間というコストとなって跳ね返り、開発者の認知的コンテキスト・スイッチを強制し、生産性を食いつぶす。
今回は、単なる`cargo build`の高速化を超え、`rustc`の内部構造とリンカの挙動をハックし、CI/CDパイプラインを「音速」に近づけるための真の最適化術を伝授する。
—
1. リンク時間を支配せよ:`lld`と`mold`の使い分け
Rustのビルド時間の大半は、実はコード生成ではなく「リンク」に費やされていることが多い。特に大規模なマイクロサービスでは、デフォルトのシステムリンカ(`bfd`や`gold`)はボトルネックだ。
`mold`による劇的な短縮
現代のリンカの最適解は間違いなく `mold` である。`mold`はマルチスレッド化が極限まで進められており、リンク速度は従来のリンカの数倍から数十倍に達する。
.cargo/config.toml
[target.x86_64-unknown-linux-gnu]
moldをリンカとして指定する設定
linker = “clang”
rustflags = [“-C”, “link-arg=-fuse-ld=/usr/bin/mold”]
なぜこれが効くのか:
`mold`はリンク時のシンボル解決プロセスを並列化し、メモリマッピングを最適化する。CI環境で`mold`を導入するだけで、リンクフェーズの時間を80%以上削減できるケースも珍しくない。
—
2. コンパイル時間をハックする:`codegen-units`と`target-cpu`
デフォルトの`cargo build`は汎用性を優先するが、実務環境では「特定のターゲットマシン」に最適化することでコンパイラの負荷を劇的に下げられる。
コア数の制約を最適化する
`codegen-units = 1`は最適化レベルを上げるが、コンパイル時間を爆増させる。開発環境では`16`以上、CIでは`4`程度に設定し、並列性と最適化のバランスを制御すべきだ。
[profile.dev]
開発中は最適化よりも「速さ」を優先
codegen-units = 256
incremental = true
[profile.release]
リリース時はターゲットCPUを明示し、最適化パスを絞る
codegen-units = 1
lto = “thin” # フルLTOは遅すぎるため、thin LTOを推奨
`target-cpu=native`の罠と効能
`target-cpu=native`は、ビルド実行マシンのCPU命令セット(AVX-512など)をフル活用する。注意点は、CI環境と本番環境のCPUアーキテクチャが一致している必要があることだ。これを守れば、実行時のパフォーマンスとビルド時の命令生成効率が飛躍的に向上する。
—
3. Dockerパイプラインにおける「層」の再設計
Dockerでのビルド失敗の最大の要因は、「キャッシュの無効化」である。`Cargo.toml`をコピーしただけで`cargo build`を走らせていないか?
賢いビルド・ステージング
`cargo-chef`を使用し、依存関係のロックファイルのみを元に「依存関係だけを先にビルドする」層を作ることは常識だが、さらに踏み込んで`sccache`を統合する。
sccacheをCIコンテナに配置し、共有キャッシュとして利用
ENV RUSTC_WRAPPER=/usr/local/cargo/bin/sccache
ENV SCCACHE_DIR=/sccache-cache
マウント時にキャッシュを永続化
RUN –mount=type=cache,target=/sccache-cache \
–mount=type=cache,target=/usr/local/cargo/registry \
cargo build –release
アーキテクトの知見:
`sccache`は、ローカルビルドの結果をGCSやS3等のオブジェクトストレージに共有できる。チームメンバー全員でキャッシュを共有すれば、誰かが一度ビルドしたクレートは、他人のマシンでは「一瞬で」解決される。これが真のチーム単位での高速化だ。
—
4. コンパイル・プロファイリングによるボトルネックの特定
「遅い」と推測して設定を変えるのは素人だ。`rustc`はコンパイルの各フェーズでどこに時間がかかっているかを出力できる。
ビルドのボトルネックを特定するための魔法のコマンド
cargo build -Z timings
このコマンドを実行すると、`target/cargo-timings/`ディレクトリに詳細なHTMLレポートが生成される。どのクレートが並列化の阻害要因(クリティカルパス)になっているか、可視化して叩き潰す。依存ツリーの深すぎるクレート(`proc-macro`多用系など)は、リファクタリングの対象として即座にリストアップせよ。
—
5. 終わりに:DevOpsの美学
Rustのビルド最適化は、単なる設定値の調整ではない。それは「コードの依存構造」というソフトウェアの骨格を理解する作業に他ならない。
1. リンクを`mold`で叩く。
2. `sccache`でビルド結果を共有する。
3. `timings`で真のボトルネックを可視化する。
これらを実行するだけで、CIの時間は数十分単位で短縮され、開発者の体験(DX)は劇的に改善される。伝説のDevOpsアーキテクトとして言わせてもらえば、「ビルド時間を短縮することは、製品の市場投入までの時間を短縮すること」と同義である。
さあ、今すぐあなたの`.cargo/config.toml`を書き換え、コンパイラを極限まで加速させろ。コードが速くなるのではない、あなたの未来が速くなるのだ。