一見すると単純なリスト更新処理でも、CPUが継続的に動作し続けることがあります。また、間隔が短すぎるタイマー、重複したネットワークリクエスト、バックグラウンドタスクによって、ウェイクアップ回数が増える場合もあります。通常、機能テストではエラーにならず、コードカバレッジからも問題は見えません。こうした変化をマージ前に検出するには、OVPSのクラウドMac上でテスト環境を固定し、同じ一連のユーザー操作をxctraceで記録して、確認済みのベースラインと比較します。
ゲートで計測する対象を先に定義する
消費電力は、利用状況から切り離された単一の値ではありません。ホーム画面でのアイドル状態、連続スクロール、画像のデコード、バックグラウンド同期では、リソースの特性がまったく異なります。同じベースラインにまとめてはいけません。まず、60~120秒継続し、安定して再現できる主要な操作フローを選びます。たとえば、アプリを起動し、メッセージ一覧を開き、3画面分スクロールして、詳細を開いてから戻るという流れです。
各シナリオでは、少なくとも次の条件を記録します。
- Appのコミットリビジョンとビルド構成
- デバイスモデル、OSバージョン、バッテリー残量の範囲
- 画面の明るさ、ネットワークの種類、低電力モードの状態
- テストアカウントのデータ量
- サンプリング時間、ウォームアップ回数、本計測の実行回数
シミュレータは、自動化スクリプトと操作が安定しているかを検証する用途には適していますが、実機の消費電力を再現するものではありません。正式なゲートには固定した実機を使用し、シミュレータの結果はプロセスの動作状況を示す補助的な証拠としてのみ扱います。
初回の実行結果をそのまま採用してはいけません。初回起動時には、データベースのマイグレーション、シェーダーの準備、キャッシュの生成などが行われる場合があります。最初に1回ウォームアップし、その後に少なくとも3回の本計測を実施します。偶発的なシステムタスクによるノイズを抑えるため、評価には中央値を使用します。
クラウドMacとテストデバイスの状態を固定する
実行ノードではXcodeのメジャーバージョンを固定し、Developerディレクトリを明示的に指定します。対話型Shellで偶然設定されている環境変数に依存してはいけません。
set -euo pipefail
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
xcodebuild -version
xcrun xctrace version
xcrun xctrace list devices
xcrun xctrace list templates
最後の2つのコマンドは互換性チェックも兼ねています。利用できるテンプレートやエクスポート構造はXcodeのバージョンによって変わる可能性があるため、スクリプトではEnergy Logが常に存在するものと仮定してはいけません。テンプレートが見つからない場合は直ちに終了し、バージョン情報を保存します。意味のない空のサンプリングにフォールバックしてはいけません。
実機は計測前に毎回同じ状態へ戻します。無関係なアプリを終了し、バッテリー残量を近い範囲に保ち、温度が通常の状態まで戻っていることを確認します。自動アップデートを無効にし、ネットワーク条件も安定させてください。テスト中にアーカイブ、依存関係のダウンロード、ディスクのクリーンアップを同時実行してはいけません。共有ノード上の追加負荷は、CPUとI/Oの測定値を汚染します。
実行前チェックを用意する
デバイスのUDID、Bundle ID、シナリオ名、コミット番号を同じ実行ディレクトリに保存します。ディレクトリ名は一意にする必要がありますが、トークンや署名情報をパスやログに含めてはいけません。
RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)-${GIT_COMMIT:-local}"
OUT_DIR="artifacts/energy/${RUN_ID}"
mkdir -p "$OUT_DIR"
xcrun simctl list devices > "$OUT_DIR/devices.txt"
xcrun xctrace list templates > "$OUT_DIR/templates.txt"
git rev-parse HEAD > "$OUT_DIR/commit.txt"
実機を接続する場合、最初のコマンドはチーム独自のデバイス検出コマンドに置き換えられます。重要なのはコマンドの形式ではなく、検出に失敗した時点で計測を停止することです。「デバイスが接続されていない」状態を「消費電力が低下した」と誤判定してはいけません。
再現可能なxctraceトレースを記録する
計測対象のプロセスを起動してウォームアップを完了してから、プロセス名を指定してアタッチします。次のスクリプトでは、デバイス、プロセス、テンプレートをCIパラメータで明示的に指定する必要があります。
DEVICE_UDID="${DEVICE_UDID:?missing DEVICE_UDID}"
PROCESS_NAME="${PROCESS_NAME:?missing PROCESS_NAME}"
TRACE="$OUT_DIR/energy.trace"
xcrun xctrace record \
--template "Energy Log" \
--device "$DEVICE_UDID" \
--attach "$PROCESS_NAME" \
--time-limit 90s \
--output "$TRACE"
記録を開始した後、UI自動化によって決められた一連の操作を実行します。操作スクリプトでは画面座標ではなく、アクセシビリティ識別子を使用してください。テストデータは事前に投入し、ネットワークリクエストは安定したテスト環境へ送ることが望まれます。ログインの失敗、操作を遮るダイアログ、目的の画面に到達できない問題が発生した実行は無効とし、中央値の計算に含めてはいけません。
xctraceが成功を返しても、それはトレースが生成されたことを示すだけで、シナリオが正しく実行されたことを保証するものではありません。各記録では、UIテスト結果、開始時刻と終了時刻、アプリケーションログの要約、シナリオ完了マーカーも保存します。いずれかが欠けている場合、ゲートは性能テストの合格ではなく「計測無効」と報告する必要があります。
メトリクスをエクスポートしてベースラインと比較する
まずトレースの目次をエクスポートして、現在のXcodeで利用できるテーブルを確認します。そのうえで、バージョンごとに解析ルールを管理します。
xcrun xctrace export \
--input "$TRACE" \
--toc \
--output "$OUT_DIR/toc.xml"
バイナリ形式のトレースを、壊れやすい1本の正規表現で直接解析してはいけません。より堅牢な方法は、XcodeのメジャーバージョンごとにXPathまたはXMLパーサーを管理し、元のトレースも併せてアーカイブすることです。ゲートでは、継続的なCPU動作、スレッドのウェイクアップ、タイマーの発火頻度、ネットワーク転送量という4種類の変化に注目できます。これらは原因を特定するための手掛かりであり、単一の「消費電力スコア」に乱暴に集約すべきではありません。
ベースラインには、同じデバイス、同じシナリオ、同じビルド種別で正常に完了した複数回の実行結果を使用します。直近で確認済みのバージョンの中央値を保存しつつ、各実行の生データも保持することを推奨します。比較時には、相対的な変化率と絶対値の下限を組み合わせて判定します。非常に小さい値は、2倍になってもエンジニアリング上の意味がない場合があります。
異常を段階的に処理する
軽微な変動では、まず警告を出し、マージはブロックしません。しきい値を連続して複数回超えた場合や、CPUとウェイクアップが同時に悪化した場合に失敗とします。しきい値はチームの過去のサンプルに基づいて決定し、一般的なパーセンテージをそのまま流用してはいけません。
失敗レポートには、少なくともコミット番号、デバイスとOSのバージョン、3回分の測定値、中央値、ベースライン、変化率、トレースのパス、UIシナリオの結果を含めます。これにより、開発者は「消費電力が高すぎる」という一文だけを見るのではなく、証拠を直接確認できます。
異常なトレースからコードへ戻る
CPU使用率が継続的に高い場合は、まずメインスレッドでのポーリング、画像処理、レイアウトの重複計算、終了していないバックグラウンドキューを確認します。ウェイクアップ回数が増えている場合は、短い間隔のタイマー、頻繁なディスク書き込み、重複した通知、集約されていないネットワーク再試行を重点的に調べます。ネットワーク動作に異常がある場合は、ページネーションリクエスト、キャッシュヒット率、テレメトリのバッチ処理、再接続ポリシーを確認してください。
よくある誤判定の要因も個別に除外する必要があります。デバイスを充電した直後の温度変化、初回実行時に続いているキャッシュ生成、テストアカウントのデータ量の変化、システムダイアログによる操作の中断、クラウドMac上で同時実行されている別の高負荷タスクなどです。修正後は同じ条件で3回すべてを再実行しなければなりません。1回だけ良好だった結果で、失敗記録を上書きしてはいけません。
最終的に、消費電力の回帰ゲートの価値は、見栄えのよいスコアを生成することではありません。テストシナリオ、デバイス条件、元のトレース、コードのコミットを関連付けることにあります。これらの証拠を繰り返し収集できて初めて、異常の原因を明確に特定でき、ゲートが日常的に無視されるノイズになることも防げます。
よくある質問
iOSシミュレータだけで消費電力を判定できますか?
できません。スクリプトとシナリオの安定性確認には使えますが、最終的な基準値は機種とOSバージョンを固定した実機で作成します。
基準値を一度超えたらマージを停止すべきですか?
いいえ。少なくとも3回計測して中央値を比較し、超過が継続し、確認可能なtraceが残っている場合にだけ停止します。
次回のビルドを専有物理ノードで実行する
3種類の Apple Silicon 構成と、販売中の6つのノードから選択できます。実際の利用可能状況は、コンソールにリアルタイムで表示される情報をご確認ください。