結論先行
- 3倍の高速化は専用M4ベアメタル+ウォームDerivedData+並列ノードから生まれ、コンパイラフラグの追加ではない。
- ローカルMacBookは参入障壁ゼロ、GitHub Actionsは弾力性、共有Mac VPSは安価だがコンテキストを温められない。ベアメタルレンタルはローカル体験を課金可能なRunnerへ移す。
- 対照表の五列 Entry / Execution / Context / Cost / Permission——多くのチームはCPUではなくContext(DerivedData、Keychain、inode)で失点する。
- コールドスタートarchiveとウォームキャッシュarchiveは2〜3倍差がありうる。リリース週はDerivedDataパス固定と無意味な
flutter clean禁止が必須。 - 意思決定マトリクス:日次ビルド<5はローカル、CI中心は自ホストベアメタル、コンプライアンス分離はXcode Cloud、ハイブリッドはスタックA/B/C。
- 関連読み物:Archive全文、Flutter Runner、メモリswapガバナンス、codesign——文末クラスターリンク参照。
Xcodeビルドが遅いと誤解される理由——「マシンが遅い」ではない
Xcodeビルド最適化の話になると、まずメモリ増設、-jobs、Swiftコンパイルフラグが挙がる。しかし実際のiOS/Flutterパイプラインでは、xcodebuild archiveのばらつきは実行コンテキストの再利用可否に支配される。DerivedDataのSSDパス固定、CocoaPodsモジュールグラフの索引、Keychainの毎回再構築、リリース週のinode競合などが本丸だ。
ローカルMacBookで8分のビルドがGitHub Actionsで20分になるとき、Apple Siliconが遅くなったのではない。CIは使い捨て環境として扱い、毎回コールドチェックアウト、pod再解決、証明書インポートが走る。共有Mac VPSでは隣テナントのCPU/IO奪取、キャッシュ退避、夜間バックアップでさらに遅く見える。
- 誤解1:
-jobsやSWIFT_COMPILATION_MODEだけ見てDerivedDataパス漂移を無視。 - 誤解2:コールドCI1回とローカルを比較し、ウォームパス中央値を測らない。
- 誤解3:共有VPSの月額安さをクラウドMac総コストと同一視し、エンジニア待機とリトライを無視。
- 誤解4:リリース週に増設するがXcode/Ruby/CocoaPodsを固定せず、キャッシュを全破棄。
- 誤解5:シミュレータとarchiveを16GBで同時実行しswapで2倍遅延——メモリ治理記事参照。
結論:ベアメタルレンタルはローカルMacの再利用可能コンテキストを製品化する。専用M4、ディスク枠固定、SSH Runner、ウォームDerivedData、必要なら第二並列ノードで、コールドCIに対しウォームarchive中央値を約1/3(≈3倍高速)にできる。魔法のフラグではない。
ベアメタル3倍高速化の三本柱
「3倍」は同一ブランチ・同一Podfile.lock・Release archiveで、ウォームパス中央値を「GitHub Actionsコールド+共有VPS」基準と比較した値。三本柱は相互依存で、一つ欠ければ倍率は落ちる。
柱1:専用M4ベアメタル(共有VPSではない)
物理専有はCPU・メモリ帯域・SSD書き込みが未知テナントに割り込まれないこと。iOSビルドは安定IO上の索引と増分コンパイルに依存し、共有VPSはCPU低負荷でも極端に遅い「偽の空闲」が出る。契約ではarm64実機、DEVELOPER_DIR固定、DerivedData長期マウント許可を書面確認。
柱2:ウォームDerivedData+パス固定
DerivedDataはオプションキャッシュではない。Swift/Clangモジュールグラフと増分状態の器だ。ランダムtempや毎回cleanで8分ウォームが18分コールドに戻る。Runner初期化で/Users/ci/DerivedData/AppNameを作り、-derivedDataPathを明示。リリース週の不要なflutter cleanは禁止。Archive/Flutter Runner記事参照。
柱3:並列ノード(ビルドとテスト分離)
第二台は常に「より速いCPU」ではない。並列が目的:xcodebuild archiveとcodesign専用機と、XCTest/スモークシミュレータ専用機。16GB単機のswapを避ける。日次15ビルド超なら、リリース週のM4日次レンタル第二ノードは24GB単機増設より壁時計短縮に効くことが多い。
五つの実行面:Entry / Execution / Context / Cost / Permission
調達とアーキテクチャレビュー用。Entryは着手コスト、Executionはarchive予測可能性、ContextはDerivedData/Keychain/ディスク常駐、Costは2026年中小チームの総コスト感、Permissionは証明書・公証・ネットワーク統制。
| 方式 | Entry | Execution | Context | Cost | Permission |
|---|---|---|---|---|---|
| ローカルMacBook | 既存機ならゼロ障壁 | ウォーム極速、出張/シャットダウンで中断 | DerivedData常駐、個人Keychain | ハードウェア sunk cost、並列化困難 | 証明書自由、監査弱い |
| GitHub Actionsホスト | YAMLで開始 | コールドばらつき、キュー待ち | コンテキスト非永続、cache miss | 分課金、大リポ高コスト | 毎回署名bootstrap |
| 共有Mac VPS | 低月額で惹きつけ | 性能不可測、隣接干渉 | DerivedDataよく削除 | 表示安価、待機コスト隠れ | SSH可、専有保証なし |
| ベアメタルレンタル(M4専用) | 日次PoC+SSH | ウォームarchive安定、ノード追加可 | DerivedData/Keychain長期保持可 | 日/週柔軟、リリース週ROI高 | 自ホストRunner、証明書方針自控 |
| Xcode Cloud | Appleエコシステム統合 | 標準パイプライン、カスタム制限 | Apple管理キャッシュ | compute課金、大monorepo要評価 | ASC署名深統合 |
「CIがローカルより3倍遅い」多くはContext列ゼロ点が原因で、ExecutionのCPU不足ではない。
コールド vs ウォーム:archiveベンチマーク(サンプル)
サンプル:中規模Flutter iOS(Swift/ObjC約180ファイル、ローカルPod 12)、Xcode 16.x、Release archive+IPA。分数は10回中央値。絶対値コピーせず自前測定を。
| 環境 | コールドarchive | ウォームDerivedData archive | 備考 |
|---|---|---|---|
| ローカルM4 MacBook Pro 16GB | 11.2 | 7.4 | 個人Keychain、索引揺れ |
| GitHub Actions macos-14 | 21.8 | 14.6 | cacheもpath/key依存 |
| 共有Mac VPS(4 vCPU表示) | 19.5 | 13.1 | 隣IOピークで+30% |
| 専用M4ベアメタル(単一ノード) | 12.0 | 6.8 | derivedDataPath固定 |
| ベアメタル二重ノード(ビルド/テスト分離) | — | 壁時計6.8(並列) | archiveとXCTest別ホスト |
ホストコールド21.8分に対しベアメタルウォーム6.8分は約3.2倍。毎回DerivedData cleanを続けるとベアメタルもコールド域に戻る——最適化対象はコンテキストでありバッジではない。
意思決定マトリクス:ベアメタルRunnerを入れるべきか
五つのチーム像で即断。二行以上「ベアメタル優先」なら日次レンタルPoC一週間でウォーム中央値を記録。
| チーム像 | 日次ビルド頻度 | 署名複雑度 | 推奨 | 理由 |
|---|---|---|---|---|
| 個人開発者 | <3/日 | 単一証明書 | ローカルMacBook | コンテキスト既にローカル、クラウドROI低 |
| 小規模Flutterチーム | 5〜15/日 | 多flavor+Pod | ベアメタル単一+自ホストRunner | ウォームDerivedData効果最大 |
| 受託並行多案件 | ピーク30+/日 | 複数Team ID | ベアメタル二重ノード | ビルド/テスト分離でswap回避 |
| 規制金融/医療 | 中程度 | HSM/監査 | ベアメタル+ネットワーク分離 | Permission列の自控が必要 |
| 純Apple小チーム | 低 | ASC一体 | Xcode Cloudまたはローカル | カスタム少なければ十分 |
推奨スタック A / B / C
成熟度三段階——Aを一週間試し、B/Cへ段階移行。
スタックA:ホストCI+パス衛生(最小変更)
GitHub Actions継続し、-derivedDataPath、pod install --deployment、署名job分割、concurrencyで古いビルドキャンセル。PMF検証中・日次<5向け。20〜35%短縮は現実的だが3倍は稀。
スタックB:単一ベアメタル自ホストRunner(スイートスポット)
専用M4をレンタル、launchd Runner、DerivedDataとPodsを同一SSDに永続化、GitHub/GitLabトリガー。Flutter Runnerとcodesign記事でKeychain一度設定。安定リリースの中小チーム向け。
スタックC:二重ノード+archive専用(リリース週)
主ノードはウォームarchive、副ノードはテストと公証スクリプト。リリース週はhotfix用第三台を日次追加。Archive全文とメモリswap治理で16GBピーク崩壊を防ぐ。
ベアメタルでも救えない落とし穴
- 毎CIで
flutter cleanやDerivedData削除——コールドを選択している。 Podfile.lock未コミットでpod解決が不定。- Runnerで
brew upgradeXcode——リリース週にキャッシュと署名が全滅。 - 16GBでシミュレータ+archive同時——swapで2倍。
- 冪等でない証明書インポートがKeychain再作成で署名遅延。
- 10回中央値ではなく1回最速だけ比較——調達をネットワークノイズで誤る。
7ステップ導入チェックリスト(チケット貼付可)
- ベースライン:現CIでarchive10回の段階時間(checkout/pod/compile/sign)。
- パス固定:Runnerに永続
DerivedDataとPodsを作成し文書化。 - 日次PoC:専用M4ベアメタルで同一workflow10回、ウォーム中央値記録。
- 署名:codesign記事どおりCIユーザーとKeychain解除。
- 並列:XCTestとarchiveがRAM競合なら第二ノードまたはcronずらし。
- ガバナンス:ディスク/inodeとswapアラート(メモリ記事)。
- 調達:ウォーム中央値とエンジニア時給でROI算出後、週/月契約。
FAQ
コンパイラフラグだけで3倍は可能?
難しい。増分Swiftコンパイル、モジュールキャッシュ、リンクが支配的。フラグはclean向けで、CIばらつきの主因であるコンテキスト喪失には弱い。
ベアメタルとクラウドMacの違いは?
クラウドMacはカテゴリ名で専用を意味しない。物理専有、arm64、ディスク枠、DerivedData長期保持を書面確認。共有VPSもクラウドMacと呼ばれる。
GitHub Actions cacheでは足りない?
緩和はするがホットSSD状態の完全代替にはならない。key漂移、restore失敗、巨大DerivedDataの上下伝送が利益を食う。自ホストベアメタルはウォームをローカルに近づける。
Xcode Cloudの方が簡単?
ASC中心でカスタム少なら省力。Runnerスクリプト独自、マルチリポ、Flutter混在なら自ホストベアメタルが柔軟。
16GBで足りる?
単一archiveなら多くは可。並列シミュレータ+複jobは24GBまたは二重ノード。swap監視がCPU増設より先。
ROIはいつ見える?
日次8ビルド超でCIがローカルより12分以上待つなら、一週間PoCで明確化しやすい。リリース週バーストは日次課金が合理的。
まとめ
Xcode最適化の正しい物語は実行コンテキストの保持であり神秘フラグではない。専用M4ベアメタル+ウォームDerivedData+必要時の第二並列ノードで、ウォームarchiveはコールドホストCIの約3倍速——サンプルと本番チケットで繰り返し見る数量級だ。
- CPU購入前にContext列を読む。
- 調達は10回ウォーム中央値で、外れ値1回ではない。
- 多くはスタックB、リリース週はCへ。
次:7ステップで一週間PoCし、Archive・Flutter Runner・メモリ・署名の関連記事を繋ぎ、「一度速い」を「毎週速い」にする。