「同一個 CI 任務越跑越久」不能直接推導出 Mac 變慢。Git LFS 官方文件明確區分指標檔案與 LFS 物件;fetch 完成也不等於工作區已經填入完整檔案。Git LFS 機制說明 是判斷這個邊界的依據。

症狀: iOS CI checkout 階段拉長,團隊直覺想增加 Mac 建置機。
最快解法: 先分別量 Git 資料、LFS 物件、工作區恢復、依賴與 Xcode 建置;只有 CPU、記憶體或建置佇列持續飽和,才擴充固定或彈性遠端 Mac。

這篇文章適合維護大量 Git LFS 資源、且 iOS CI 檢出階段明顯變慢的研發效能負責人。
如果你負責 Mac 建置容量、憑證隔離、快取污染或企業基礎設施預算,本文可作為試點驗收與採購判斷表。

01

先看哪個指標:Mac 真的慢,還是資料路徑在等待?

Git LFS 為什麼會讓 iOS CI checkout 時間越來越長?常見原因不是單一的 Mac 效能下降,而是每次任務拉取了不必要的物件,或快取沒有真正命中。你需要把 checkout 拆成可比對的階段,而不是只讀取 CI 平台顯示的總耗時。

建議在同一個 commit、同一個 Xcode 建置指令和同一組依賴條件下,建立兩組基線:

  • 冷啟動基線:清除工作區與可控的 LFS 物件快取後執行。
  • 重複執行基線:保留允許復用的快取,再執行相同任務。
  • 記錄 Git 物件傳輸、LFS 物件下載、工作區填充、依賴恢復與 Xcode 建置的起止時間。
  • 同時保留下載位元組、失敗重試、磁碟使用量和節點等待時間。

判斷原則很直接:

  • 網路等待和 LFS 下載佔主要比例:先優化資料路徑、拉取範圍或快取。
  • 工作區填充反覆耗時:檢查 checkout 行為、深度、分支範圍和工作區是否可安全復用。
  • Xcode 建置期間 CPU 或記憶體長時間飽和:才評估 Mac 節點規模。
  • 任務在佇列中等待,但單次建置不飽和:優先檢查節點數與排程,而非升級單台 Mac。

這也是「Git LFS 下載慢時,應優化網路還是增加 Mac 建置機」的實際判斷方式:先看階段時間和下載量,再決定資源類型。增加 Mac 只能增加可同時執行的建置能力,不能縮短一個被資料傳輸卡住的 checkout。

建議的階段計時表

指標 要記錄的證據 代表的瓶頸 優先處置
Git 物件傳輸 clone、fetch 的時間與位元組 Git 歷史或分支範圍過大 調整深度、分支與任務範圍
LFS 物件下載 實際下載量、重試與來源 LFS 儲存端或網路路徑 路徑過濾、快取、頻寬
工作區恢復 checkout 或填充時間 指標檔案與物件使用方式不一致 復核 checkout 流程
依賴恢復 套件快取下載與解壓時間 依賴快取失效 重新設計快取鍵
Xcode 建置 編譯、連結、簽署時間 Mac CPU、記憶體或磁碟 I/O 評估節點擴充
佇列與恢復 等待、失敗重試、重新分配 節點容量或故障冗餘 固定池、彈性池或混合模式

不要把某次任務的總時間當作唯一硬指標。只有在相同輸入、相同工作流程下比較,冷啟動與重複執行的差異才有決策價值。

02

拉取範圍如何改變每次流水線的資料成本?

Git LFS 指標檔案很小,真正的二進位資源則以 LFS 物件形式管理。取得 Git 歷史、下載 LFS 物件,以及將物件填入工作區,是三個不同動作。Git LFS fetch 手冊 說明了 fetch 的物件取得行為;Git clone 官方文件 則可用來核對 clone 的深度、分支和工作樹設定。

CI 中可以只下載目前任務需要的 Git LFS 檔案嗎?可以,但必須先確認任務所需的資源集合,而且要把過濾條件納入可重現的流水線設定。Git LFS 的 includeexclude 不是「下載完成後刪除檔案」;它們會影響要取得哪些物件。最小診斷片段可保留為:

git lfs fetch --include="path/to/assets/**" --exclude="path/to/assets/test/**"
git lfs checkout

這段指令只能作為隔離倉庫中的驗證起點。正式導入前,請確認 checkout 元件是否自行管理 LFS,以及它是否覆寫深度、憑證或工作區策略。checkout 元件參數文件 明確提醒,不同版本和設定會影響檢出行為,不能只依賴 Git LFS 指令名稱推測結果。

以任務資源集合取代全量拉取

拉取策略 適合的任務 優點 風險與驗收
全量拉取 發布、完整回歸、需要所有資源的建置 流程簡單,資源缺失風險較低 每個 PR 都承擔不必要的傳輸
路徑 include/exclude 單一模組、指定平台或資產集 降低下載範圍 路徑變更可能造成隱性缺檔
任務拆分資源集 圖片、影片、模型等大型資源分屬不同工作 可按工作需求拉取 工作間依賴和快取鍵更複雜
淺層與指定分支 PR 驗證只需當前提交 減少 Git 歷史傳輸 需要版本標籤或完整歷史的任務不適用

請先盤點倉庫實際的 LFS 物件清單,再按 PR 驗證、夜間回歸和發布建置分組。不要因為 fetch 成功就判定工作區可用;驗收時必須檢查關鍵路徑是否由指標檔案變成完整內容,並讓建置產物或資源校驗失敗時立即中止。

03

快取命中率與工作區隔離,哪一個更影響遠端 Mac?

自託管 Mac 如何復用 Git LFS 快取而不污染工作區?關鍵是把「物件快取可復用」和「工作區可復用」分開管理。前者保存可驗證的 LFS 物件,後者保存特定 commit 的檔案狀態;兩者的生命週期、權限和清理條件不應相同。

你至少要記錄以下指標:

  • 實際下載位元組和重複物件比例。
  • 快取命中前後的 LFS 階段時間。
  • 快取目錄的磁碟增長趨勢。
  • 工作區是否曾殘留上一個分支的檔案。
  • 清理後重新執行能否得到同樣的資源校驗結果。

長期在線的專用 Mac 適合受控復用。它可保留經過驗證的物件快取,但每次任務仍應以乾淨的工作區、明確的 commit 和可追溯的快取鍵開始。共享工作區的優點是少做初始化,缺點是殘留檔案、錯誤權限和跨分支污染更難排查。

彈性遠端 Mac 則不應假設一定有熱快取。你可以用可信的預熱任務、分層資源集或預先同步的快取降低冷啟動影響,但實際收益必須來自同一條 iOS CI 流水線的冷、熱基線。沒有企業記錄或本站實測,就不要宣稱固定節點一定快多少,也不要用外部典型值代替你的倉庫資料。

第一步:先建立可清理的快取邊界

快取鍵至少應包含專案、資源集合、版本或提交範圍與信任等級。清理策略則應同時有:

  1. 磁碟容量門檻。
  2. 長時間未使用物件的回收條件。
  3. 任務失敗後的工作區清理。
  4. 發布節點與 PR 節點的物理或權限隔離。
  5. 清理後的完整性重跑。

依賴快取也不能和 LFS 物件快取混為一談。官方 CI 快取安全文件指出,快取內容可能被同一儲存庫後續執行的程式碼讀取;因此,快取鍵、分支信任和敏感資料不能只靠目錄名稱區分。官方依賴快取安全說明 可作為設計快取存取邊界的參考。

04

憑證和資源完整性,如何限制加速方案?

加速後最危險的結果,不是任務多花幾分鐘,而是建置在缺少資源的狀態下仍然產出看似成功的結果。請把以下檢查加入驗收:

  • 關鍵 LFS 路徑必須通過內容或雜湊校驗。
  • 失敗的物件下載不能被空檔案、指標檔案或舊工作區內容掩蓋。
  • 發布節點的簽署權限不得因為快取需求而下放給一般 PR。
  • LFS 下載憑證、原始碼存取權和程式碼簽署權限分開管理。
  • 非可信分支不得繼承生產發布節點的長期憑證。

Git LFS 凭證、倉庫令牌、持久化工作區和跨專案快取會形成不同暴露面。下載權限只解決「能否取得資源」,不代表可以進行簽署或發布。對自託管 Runner,應再檢查工作區清理、節點標籤、網路出口、日誌遮罩和任務完成後的令牌處理。自託管 Runner 安全文件 提供了自託管執行環境的風險邊界。

第二步:用可重複任務驗收完整性

準備一個不修改原始碼的驗收工作,依序完成:

  1. 取得指定 commit,不使用浮動分支。
  2. 記錄 Git 和 LFS 下載量。
  3. 執行指定路徑的工作區恢復。
  4. 檢查關鍵資源不是 LFS 指標檔案。
  5. 執行資源雜湊或專案內建校驗。
  6. 執行最小 Xcode 編譯或測試。
  7. 清理工作區後再次執行,對比結果。

若第二次任務依賴第一次殘留的檔案才能成功,這不是快取命中,而是工作區污染。此類節點不應直接承接生產發布工作。

05

節點吞吐指標決定擴容方向

Git LFS 優化後,仍需用四個容量指標判斷節點是否不足:有效建置時間、峰值到達率、排隊時間和故障冗餘。不要用開發者人數或硬體宣傳規格直接估算節點數,因為同一團隊的 PR、夜間回歸和發布工作負載可能完全不同。

可以用不帶預設金額的 TCO 模型比較方案:

TCO = 網路流量成本 + 儲存成本 + Mac 佔用時間 + 維運工時 + 故障影響成本

其中,Mac 佔用時間應按實際任務和佇列記錄計算;網路與儲存則按你的供應商帳單或內部成本模型填入。未取得真實價格前,不要預填每月金額或宣稱某方案節省固定百分比。

觀察到的證據 優先方案 不應先做的事
LFS 下載等待佔主要時間 路徑過濾、快取與資料路徑優化 直接購買更多 Mac
下載量下降但 Mac 編譯持續飽和 增加固定建置節點 只升級 LFS 儲存端
單次建置不飽和但佇列很長 增加可並行節點或彈性遠端 Mac 只更換單台更快的 Mac
快取造成跨專案污染 專案、信任等級和工作區隔離 擴大共享快取範圍
峰值短、平日負載低 固定可信節點加彈性容量 為全年峰值購買全部實體機
需要穩定簽署與物理介面 專用固定 Mac 池 將生產簽署工作完全放到不受控共享節點

固定 Mac 池適合發布簽署、長期快取和可預測負載。彈性遠端 Mac 池適合短時間峰值、試點和不值得全年持有的容量。混合模式則保留少量可信固定節點,把 PR 驗證、夜間回歸或峰值併發交給彈性節點。

如果你要比較不同地區的遠端 Mac 交付方式,可先查看 KVMNODE 的遠端 Mac 方案頁面,再用同一份流水線驗收,而不是以節點規格表取代實際測試。

06

第三步:用驗收矩陣決定「只優化、擴容或混合」

在採購或遷移前,把每一項結果寫成「證據、門檻、失敗處置」。不要只留下「速度變快」這類無法稽核的結論。

建議矩陣至少包含:

  • 冷啟動:完整下載量、LFS 時間、工作區恢復時間。
  • 熱快取:重複物件比例、快取命中後時間、磁碟增長。
  • 資源完整性:指標檔案檢查、雜湊校驗、建置產物檢查。
  • 憑證隔離:PR、一般分支和發布節點的權限差異。
  • 磁碟回收:達到容量門檻後是否可清理並成功重跑。
  • 佇列容量:峰值期間等待時間和並行任務數。
  • 故障恢復:節點中斷後能否重新分配,且不使用污染工作區。
  • TCO 輸入:流量、儲存、Mac 佔用、維運與故障影響的實際記錄。

最後輸出三類結論:

  1. 只優化 Git LFS:傳輸與工作區階段是主瓶頸,Xcode 建置未持續飽和。
  2. 直接擴充 Mac 容量:資料階段已穩定,CPU、記憶體、建置佇列或故障冗餘仍不足。
  3. 固定可信節點加彈性遠端 Mac:發布需要固定隔離,峰值或非生產工作又具有明顯波動。

如果你尚未有遠端節點的真實記錄,可以先用 KVMNODE 的 Mac mini 遠端租用資訊 規劃短期 PoC;重點不是先承諾節省多少,而是將相同倉庫、相同 LFS 資源集和相同 Xcode 任務搬到試點中,取得冷啟動、熱快取、實際建置與峰值排隊證據。

當前以自購 Mac 為主的方案,常見限制是容量一次買死、峰值後硬體閒置,以及硬碟、系統更新、故障替換和遠端辦公連線都要由團隊自行維護。全雲端方案則可能面對 LFS 大物件反覆傳輸、快取失效和簽署環境隔離問題。若你已完成分階段計時,需要驗證短期峰值或跨地區團隊的 Mac 建置容量,租用 KVMNODE 的遠端 Mac 會比立即追加固定硬體更容易先取得可比較的流水線證據;但長期穩定重負載、需要物理介面,或已有成熟機房維運能力時,自建固定節點仍可能更合適。