Cloud Macで同じコミットを連続ビルドしたとき、1回目は11分だったのに4回目は15分かかったとしても、すぐに「マシン性能が不安定だ」と結論づけるべきではありません。キャッシュヒット、インデックス作成プロセス、テストの並列実行、熱圧力はいずれも似た傾向を生じさせます。適切な診断方法は、変数を固定して連続測定を行い、所要時間の増加が消費電力や熱圧力と連動しているかを確認することです。
比較可能なビルドサンプルを定義する
診断対象にすべきなのは、開発者が一時的にクリックしたSchemeではなく、安定して再現できるコマンドです。コードのコミット、Xcodeのパス、SDK、ターゲット、ビルド構成、DerivedDataディレクトリを固定し、マシン起動後のアイドル時間も記録します。実行のたびにブランチを切り替えたり依存関係を更新したりすると、測定できるのはワークロードの変化だけです。
VMOrbitの専有物理ノードでは、他のテナントの仮想マシンスケジューリングがホストリソースに干渉することはありません。ただし、ノード内ではインデックス作成、依存関係の解決、シミュレータ、以前のビルドプロセスがリソースを奪い合う可能性があります。開始前に基本的な環境情報を保存します。
mkdir -p "$HOME/build-thermal-check"
system_profiler SPHardwareDataType > "$HOME/build-thermal-check/hardware.txt"
xcodebuild -version > "$HOME/build-thermal-check/xcode.txt"
pmset -g > "$HOME/build-thermal-check/power.txt"
ps -axo pid,%cpu,%mem,etime,command > "$HOME/build-thermal-check/processes-before.txt"
コールドビルドとウォームビルドを分けて測定する
コールドビルドでは完全なコンパイル負荷を観測し、ウォームビルドでは増分ビルドの処理経路を確認します。この2つを同じ統計グループに混在させてはいけません。コールドビルドには新しい専用のDerivedDataを使用し、ウォームビルドでは直前の実行で使ったディレクトリを再利用します。ノード上の他のタスクに影響を与えないよう、グローバルキャッシュは削除しないでください。
| サンプル | DerivedData | 主な用途 |
|---|---|---|
| コールドビルド | グループごとに再作成 | 完全なコンパイルに伴う継続的な負荷を比較 |
| ウォームビルド | 同じグループ内で再利用 | 増分ビルドとキャッシュの効果を確認 |
| アイドル時の対照 | ビルドを実行しない | バックグラウンドプロセスと基準消費電力を特定 |
所要時間と熱圧力を同時に収集する
総所要時間だけでは熱スロットリングを証明できません。少なくとも3回連続で実行し、ビルド中にpowermetricsも同時に収集します。このツールには通常、管理者権限が必要です。権限付与の対象は、明示したコマンドとパラメータに限定してください。
RUN_ROOT="$HOME/build-thermal-check/run-01"
mkdir -p "$RUN_ROOT/DerivedData"
sudo powermetrics --samplers cpu_power -i 1000 -n 900 \
-o "$RUN_ROOT/powermetrics.txt" &
METRIC_PID=$!
/usr/bin/time -lp xcodebuild \
-workspace App.xcworkspace \
-scheme App \
-configuration Release \
-destination 'generic/platform=iOS' \
-derivedDataPath "$RUN_ROOT/DerivedData" \
build > "$RUN_ROOT/build.log" 2> "$RUN_ROOT/time.txt"
wait "$METRIC_PID"
pmset -g therm > "$RUN_ROOT/thermal.txt"
-n 900は最大900回サンプリングする指定です。ビルドが早く終了しても、バックグラウンドでのサンプリングは継続します。プロジェクトスクリプトからビルド終了後にサンプリングプロセスへTERMを送ることもできますが、CIにサンプリングプロセスを残さないよう、終了処理を必ず実装してください。powermetricsを使用できない場合でも、少なくともpmset -g therm、time -lp、CPU使用率順に並べたプロセスのスナップショットを保存します。
熱スロットリングは、「所要時間の傾向」と「システムシグナル」の両方に裏づけられて初めて導ける結論です。CPU使用率が一度高くなっただけで確定できるものではありません。
単一の測定値ではなく傾向から判断する
各実行の実所要時間、最大常駐メモリ、熱圧力、同時刻に高い負荷を示したプロセスを1つの記録表にまとめます。1回目が遅く、その後が明らかに速くなった場合は、通常、キャッシュのウォームアップが原因です。特定の実行だけが急に遅くなり、同時に依存関係のダウンロードやインデックス作成プロセスが確認された場合は、リソース競合の可能性が高くなります。
より注目すべきなのは、コードとキャッシュの状態が変わっていないにもかかわらず、連続実行するたびに所要時間が徐々に増え、CPUが長時間フル稼働し、それに伴って熱圧力シグナルも上昇し、負荷を止めてアイドル状態にすると次の実行で元に戻るパターンです。これらの証拠がすべて同時に確認された場合に限り、熱スロットリングを主な原因として扱うべきです。
よくある3種類の誤検知を除外する
最初に、ビルドがテスト、アーカイブ、スクリプトによるダウンロードを暗黙的に実行していないか確認します。次に、ログ内のコンパイル対象ファイル数を比較し、各実行の作業量が同じであることを確かめます。最後に、複数のxcodebuild、シミュレータ、パッケージ管理プロセスが並列実行されていないか確認します。異常が発生した実行では、次の情報を保存できます。
date -u
pgrep -alf 'xcodebuild|swift-frontend|clang|Simulator'
top -l 3 -o cpu -stats pid,command,cpu,mem,time
du -sh "$RUN_ROOT/DerivedData"
topの瞬間的な順位から分かるのは、サンプリング時点でどのプロセスがリソースを消費していたかだけです。それだけで根本原因を証明することはできません。システム状態とプロジェクトのワークロードを結びつける根拠となるのは、ビルドログ内のタスク数と継続時間です。
対照実験で発生条件を特定する
傾向を確認した後は、一度に1つの変数だけを変更します。まず、ほかの条件を維持したままCIの並列ジョブ数を1に減らします。次に並列数を元に戻し、開始時刻をずらします。最後にコールドビルドとウォームビルドを比較します。並列数を減らしたことで所要時間の傾向が安定するなら、コンパイラ自体の性能劣化よりも、同じノード上のタスク競合や継続的な高消費電力が原因である可能性が高くなります。
より積極的なキャッシュ削除を、そのまま解決策として採用しないでください。キャッシュを削除すると次の実行の作業量が増え、それまでの傾向が見えなくなります。また、再起動だけを根拠にしてはいけません。再起動はバックグラウンドプロセスを終了し、一部の状態を消去すると同時に冷却時間も生み出すため、どの変化が実際に効果をもたらしたのか判断できません。
瞬間的なクロック周波数ではなくビルドスケジュールを調整する
安定した対策は通常、同じノード上で実行する高負荷タスクの数を制限し、アーカイブ、全テスト、静的解析の実行時間をずらし、パイプラインごとに独立したDerivedDataを割り当てることです。並列実行が不可欠なタスクについては、並列数が1、2、3の場合の所要時間の中央値を先に測定し、単一タスクのピーク性能ではなく、全体のスループットが最も高くなる段階を選びます。
診断結果をCIベースラインとして定着させる
ベースラインには、コマンド、コミット、Xcodeのバージョン、ビルド種別、連続実行回数、所要時間の中央値を保存します。最速の1回を基準にしてはいけません。また、1回のタイムアウトだけでマージをブロックすべきでもありません。直近の複数回の中央値をローリング方式で比較し、しきい値を複数回連続で超えた時点で診断記録を生成するルールのほうが堅実です。
最終的な成果物には、少なくともビルドログ、timeの出力、熱圧力の記録、プロセスのスナップショット、サンプリングパラメータを含めます。問題をエスカレーションする必要がある場合は、ノードのリージョン、発生時刻、再現手順、必要最小限のログを添付します。ただし、パスワード、秘密鍵、完全なアクセス認証情報は提出しないでください。これにより、同様の変動が再発したとき、チームは原因を一から推測することなく、同じサンプルをそのまま再実行できます。
よくある質問
Xcodeビルドが一度遅くなっただけで熱スロットリングと判断できますか?
判断できません。コード、Xcode、キャッシュ、並列度を固定して最低3回連続実行し、処理時間と熱圧力、CPU電力、バックグラウンド負荷の変化を同時に確認します。
powermetricsには管理者権限が必要ですか?
通常は必要です。許可する引数を限定したsudoコマンドで採取し、出力先も管理されたディレクトリに固定する運用が適切です。
ビルドタスクを専有クラウドMacで実行
VMOrbit M4またはVMOrbit M4 Proを選び、チームの所在地に合わせてノードを選択します。実際の利用可否と提供情報は、コンソールにリアルタイムで表示される内容をご確認ください。