在雲端 Mac 建立 iOS 啟動效能回歸門檻
首頁重構合併後,功能測試全數通過,使用者卻開始反映首次開啟速度變慢。啟動效能很容易在日常開發中被忽略:新增資料庫遷移、同步讀取設定、初始化分析模組或載入大型圖片,都可能悄悄占用主執行緒的時間。與其等到人工操作時才發現問題,不如在固定的雲端 Mac 上量測冷啟動,並將其設為合併門檻。
先定義可比較的啟動情境
不要把「點開應用程式」當成完整的測試定義。至少要固定建置設定、Simulator 機型、系統執行階段、應用程式初始資料與啟動參數。測試目標也應保持單一,例如只量測從程序建立到第一個可互動畫面出現的時間,不要把登入請求或測試資料下載混入結果。
建議另外建立 Performance.xctestplan,只啟用啟動效能測試案例,並關閉隨機執行。測試環境透過啟動參數進入穩定頁面:
final class LaunchPerformanceTests: XCTestCase {
override func setUp() {
continueAfterFailure = false
}
func testColdLaunch() {
let app = XCUIApplication()
app.launchArguments = ["-uiTesting", "-resetLocalState"]
let options = XCTMeasureOptions()
options.iterationCount = 8
measure(
metrics: [XCTApplicationLaunchMetric(waitUntilResponsive: true)],
options: options
) {
app.launch()
}
}
}
-resetLocalState 應由應用程式的測試進入點處理,且只清除可重建的本機狀態。不要在正式程式碼路徑中根據這個參數略過真正需要量測的初始化流程,否則得到的只會是「測試專用的啟動速度」。
固定雲端 Mac 與 Simulator 狀態
效能門檻需要獨享實體主機,而不是在共享環境中與未知工作爭用 CPU 和磁碟。每次執行前,先確認目前的 Xcode 路徑、可用的 Simulator 與剩餘磁碟空間:
set -euo pipefail
xcode-select -p
xcodebuild -version
xcrun simctl list devices available
df -h "$HOME"
在測試計畫中指定一個已安裝的 Simulator。不要讓指令碼自動選擇「第一個可用裝置」,因為映像檔一旦變更,歷史資料就會失去可比性。門檻執行期間也應避免平行封存、相依套件更新與大規模索引工作。
效能資料首先反映的是環境,其次才是程式碼。若無法說明執行節點、建置設定與 Simulator 狀態,這些數字就不適合直接用來阻擋合併。
第一次建立基準時,應在同一個提交上重複執行。若結果的離散程度明顯偏高,應先檢查背景工作、磁碟壓力與測試資料重設邏輯,而不是立刻放寬門檻。
使用 xcodebuild 執行單一門檻
命令列工作只執行目標測試案例,並將結果套件保存為流水線產物。裝置名稱必須替換為測試計畫實際固定的機型:
set -o pipefail
mkdir -p Artifacts
xcodebuild test \
-workspace App.xcworkspace \
-scheme App \
-testPlan Performance \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-only-testing:AppUITests/LaunchPerformanceTests/testColdLaunch \
-resultBundlePath Artifacts/Launch.xcresult \
| tee Artifacts/launch-test.log
set -o pipefail 非常重要,否則即使 xcodebuild 失敗,管線末端的 tee 仍可能讓工作回傳成功。Launch.xcresult 與文字記錄都應保留:前者可用於查看每次量測與測試附件,後者則方便快速定位編譯或啟動階段的錯誤。
| 檢查項目 | 固定方式 | 發生變更後的處理 |
|---|---|---|
| Xcode | 記錄 xcodebuild -version |
先重新建立候選基準 |
| Simulator | 固定機型與執行階段 | 不與舊基準直接比較 |
| 建置設定 | 使用相同的測試計畫 | 拒絕以臨時參數覆寫 |
| 測試資料 | 透過啟動參數執行確定性重設 | 檢查重設是否完整 |
| 迭代次數 | 門檻統一執行 8 次 | 不以單次結果判定 |
建立基準,而不是追逐單次數字
在 Xcode 的測試報告中為指定測試建立效能基準,並將產生的共享基準檔案納入版本控制。基準變更應比照相依套件鎖定檔接受審查:提交說明必須清楚交代變更來源、驗證提交與預期影響,不能只寫「更新效能資料」。
門檻應區分提醒與阻擋。小幅波動可以保留作為趨勢觀察,只有在連續重新執行後仍超出容許範圍時,才將變更判定為失敗。真正的判斷依據不是某一次最快的成績,而是在同一環境下進行多次迭代後,結果是否穩定偏離已審核的基準。
以下情況不應直接更新基準:
- 測試節點同時執行了其他繁重工作;
- Simulator 機型或執行階段發生變更;
- 相依套件首次下載或索引尚未完成;
- 測試為了通過而略過初始化步驟;
- 只有一次執行出現異常,其餘結果皆正常。
失敗後保留現場並定位責任路徑
門檻失敗時,先在同一台雲端 Mac、同一個提交上重新執行一次。若結果可以重現,再依啟動階段拆分檢查:程序進入點、相依性注入、資料庫開啟、首個畫面模型建構、資源解碼與第一幀渲染。可以在這些邊界加入統一的 os_signpost,讓後續分析能看出時間耗在哪個階段,而不是根據提交規模猜測。
排查順序應從最近的變更開始,但不要只關注業務程式碼。建置設定變更、除錯診斷選項、資源大小增加與測試固定資料,也可能改變啟動路徑。修復後應同時保留失敗與通過的兩份 xcresult,並在合併請求中記錄用於對照的提交。
一套可靠門檻的價值,不在於為啟動時間貼上絕對標籤,而在於讓同一情境持續具備可比性。固定環境、版本化基準、保存證據,再將基準更新納入審查,才能讓啟動效能從主觀感受轉化為可追蹤的工程約束。
常見問題
啟動效能測試應該執行幾次?
同一提交至少執行 5 次,門檻任務建議使用 8 次以上迭代,並固定模擬器型號、系統執行環境、建置設定與背景程序。
效能門檻失敗後可以直接放寬閾值嗎?
不建議。應先在相同節點重新執行並檢查模擬器與程式路徑;只有確認變更屬於預期產品行為後,才重新建立並審查基準。
用一台可依專案啟停的雲端 Mac 重現工作流程
從三種 Apple Silicon 配置中選擇合適的資源,按日、週、月或季租用。設備為獨享物理機,並非虛擬機器;實際可用狀態以控制台即時回傳的資訊為準。