DevOps / CI/CD 2026年4月27日

2026 マトリクス:Mac mini M4 CI における並列 Xcodebuild 先、CoreSimulator 飽和、GPU/APFS IO

NodeMac チーム

インフラストラクチャ

Mac mini M4 でモバイル CI を回すチームは、CPU グラフがまだ空いているように見えると並列 xcodebuild を上げがちだ——のちにキュー p95 が伸び、各プロセスは「CPU 40% 前後」と報告するのに首を傾げる。本 2026 マトリクスは コンパイル律速 レーンと シミュレータ/IO 律速 レーンを分離し、-destination がユニファイドメモリ上でどう衝突するかを整理し、オーケストレータ YAML の横に貼れる九ステップと数値ガードレールを示す。

並列シミュレータ worker とメモリ絞り込みMac mini M4 上の UI テストシャーディング と併読し、三種類の「並列つまみ」が同じ DRAM 予算を奪い合うのを避ける。ディスク成果物の伸びが並列そのものより速いときは、Xcode を責める前に ディスク保持マトリクス と突き合わせる。

Apple Silicon CI で CPU 使用率が嘘をつく理由

ユニファイドメモリは GPU、Neural Engine、CPU コントローラが同一物理プールを共有することを意味する。CoreSimulator のフレームバッファ合成や Metal パイプライン準備に時間を使うレーンは CPU が控えめでも、Swift モジュールのコンパイル帯域を兄弟ジョブから奪う。APFS のコピーオンライトは錯覚を増幅する:シミュレータデータセットの削除と再作成を繰り返すとメタデータ I/O が跳ね上がるのに、「CPU ビジー」チャートはほとんど動かない。

  • 共有 CoreServices キャッシュ:複数 destination が同一ヘルパーデーモンとロック付きキャッシュに当たる。
  • ブートストーム:四台同時起動は一見順調でも、SpringBoard ウォッチドッグが静かに 1 レーンを再起動する。
  • Metal 競合:UI スナップショットや軽量 GPU テストでも、同一 GPU スライス上のシェーダキャッシュと競合する。

運用ルール:二つの destination が同一 udid 系と同一 DerivedData スライスを共有するなら、隔離ではなくレースを作っている。

マトリクス A — レーン種別と M4 メモリ層の安全並列度

レーン種別 24 GB 層 36–48 GB 層 メモ
Swift コンパイルのみ 重負荷 2 重負荷 3 ジョブごとの DerivedData ルートとセット。コンパイラフロントエンドのメモリスパイクに注意。
ユニットテスト(UI なし) 2 3 シミュレータ割当は依然発生——純コンパイルと比べ「タダ」ではない。
XCUITest + スクリーンショット 1 2 GPU とディスクが支配。フリート拡張はシャーディング記事に従う。

マトリクス B — 症状、ボトルネック、第一緩和策

症状 有力ボトルネック 緩和
ランダムな DTXProxy 切断 シミュレータ IPC + メモリ圧力 並列 UI レーンを減らし、スイート間にシャットダウンフックを入れる。
UI ジョブと同時にコンパイルが遅くなる ユニファイドメモリ帯域 ラベルでコンパイルと UI のプールを分割し、UI はオフピークへ。
空き 60% でもビルドが這う APFS 断片化 / inode 攪乱 週次でジョブローカルボリュームをローテーション。巨大共有 DerivedData を避ける。

オーケストレータ向け数値ガードレール

  1. ホストあたり UI 上限:24 GB ユニファイドメモリ機では、プロファイルでブート後に少なくとも 6 GB の回収可能ヘッドルームが示されない限り、同時 XCUITest destination は 1
  2. コンパイル扇出:シミュレータと混在させる場合、-parallel-testing-enabled のワーカー数を物理性能コアの 半分 に抑える。
  3. ディスク水位:CI ボリュームの APFS 空きが 18% を下回ったら新規並列 destination を停止——その下では CoreSimulator 作成が曖昧に失敗する。

容量リンク:マトリクスが 1 ホストの限界を示したら、ディスク増設だけを考える前に プール容量 SLO に並列を写し取る。

コードレビューを通る起動パターン

xcodebuild 引数を API 契約として扱う:小さなシェル関数や YAML アンカーでラップし、すべてのレーンが -derivedDataPath-clonedSourcePackagesDirPath-resultBundlePath を一貫設定する。ワンオフコマンドを CI に貼ると飽和回帰と設定ドリフトの相関が失われる。金曜夜と月曜朝で解決が変わるシェルグロブより、リポジトリに明示 -destination ブロックを置く。

マトリクスビルドは destination 名だけでなくテストクラスやターゲットでシャードし、各シャードが予測可能な GPU/IO シグネチャを持つようにする。シャードマニフェストと成果物アップロード方針を組み合わせ、失敗シャードがクリーンアップ前に xcresult を出せるようにする。オーケストレータが性能コア数と熱状態を出せるならログへ。持続的な並列 UI 負荷では macOS が静かにスロットルする——遠隔ではファンが穏やかでも。

中央キャッシュ:加速剤か IO 爆弾か

共有 DerivedData や SwiftPM キャッシュはコールドビルドを短縮するが、数十ジョブが同一ツリーにメタデータ書き込みを直列化する。集中キャッシュなら高速 APFS と inode 余裕、ジョブごとのサブフォルダ強制でロックストームをチーム横断させない。ヒット率と明示的な退避ポリシーをセットに——古い module map はミスより厄介で、手動クリアまで謎失敗が続く。

キャッシュがネットワークストレージにあると遅延スパイクが「flaky シミュレータ」に見える。ホットパスはローカル NVMe を優先し、成果物は非同期複製。どのレーンが共有キャッシュを読み書きできるか、読み取り専用ミラーかを文書化し、セキュリティレビューを追跡可能にする。

ビルドプラットフォーム担当者の九ステップ

  1. レーンにタグ:コンパイル/ユニット/UI をオーケストレータメタデータに——魔数より人間可読ラベル。
  2. destination を固定:CI ではシミュレータ UDID を明示。「最新 iPhone」名だけにしない。
  3. 週次で壁時計を測定:レーン種別ごと。回帰は赤ビルドより先に来る。
  4. DerivedData をレーン ID で隔離:マトリクス間の暗黙共有を禁止。
  5. Metal 負荷を上限:UI テストが動画を取るときは必要なら直列化。
  6. シミュレータ自動停止:各シャード後。消去周期は絞り込み記事に合わせる。
  7. IO 遅延アラート:カーネルカウンタが無い場合はステップ時間分散などの代理指標。
  8. エスカレーション文書化:スイート途中の TCC プロンプトは VNC でスポット確認。
  9. 地理的スケール:非互換レーンを 1 台のヒーローランナーに積む前に 香港・日本・韓国・シンガポール・米国 へ分散。

FAQ

xcodebuild -parallelizeTargets は CI に効くか?

マルチターゲットでは時に有効だがコンパイラフロントエンドを積む——共有ホストで全域有効化する前に計測する。

安定のためランタイムを古く固定すべきか?

再現性のため固定は合理的だが Apple のサポート終了日を追跡し、Xcode ピンとともにアップグレード窓を文書化する。

リモート Mac の SSH/VNC ガイドは?

ヘルプセンター を起点にし、GUI が要るシミュレータ問題は VNC

並列 xcodebuild destination を適正化することが Apple Silicon M4 CI を正直に保つ方法——チップは速いが ユニファイドメモリAPFS メタデータが単純並列を隠れたキューに変える。ネイティブ macOSSSH 優先の自動化と、詰まったシミュレータ向けの任意 VNC は本気のモバイル遠隔ラボの型に合う。香港・日本・韓国・シンガポール・米国専用 Mac mini M4 をレンタル すれば CapEx なしに重コンパイルと重 UI を分離でき、同一ディスクへの非互換積み上げより 物理隔離 が勝る。争いが見えたら 料金 を開いてホストを足し、並列つまみを盲信しない。

Mac mini M4 CI でコンパイルと UI を分離

SSH/VNC、HK·JP·KR·SG·US——並列が SLO を欺く前にホストを追加。

NM
NodeMac Cloud Mac
約5分でデプロイ

クラウド上の専用 Apple Silicon Mac。SSH/VNC、香港・日本・韓国・シンガポール・米国ノード。

今すぐ始める