Акция

Руководство по оптимизации Xcode: как аренда выделенного Mac ускоряет iOS archive в 3 раза (2026)

Блог Инфра runner
2026-07-20 ~9 мин

Оптимизация Xcode x3: аренда выделенного M4 bare metal + тёплый DerivedData + параллельные узлы—not compiler flags.

Сначала выводы

  1. Ускорение в 3 раза даёт выделенный bare metal M4 + прогретый DerivedData + параллельные узлы, а не дополнительные флаги компилятора.
  2. Локальный MacBook — нулевой порог входа; GitHub Actions — эластичность; общий Mac VPS — дёшево, но без тёплого контекста; аренда bare metal переносит локальный опыт на оплачиваемые runner'ы.
  3. Сравнительная таблица по Entry / Execution / Context / Cost / Permission — большинство команд проигрывают в Context (DerivedData, Keychain, inode), а не в CPU.
  4. Холодный archive и тёплый кэш могут отличаться в 2–3 раза; на релизной неделе фиксируйте путь DerivedData и запретите ритуальный flutter clean.
  5. Матрица решений: <5 сборок/день — локально; CI-first — self-hosted bare metal; комплаенс — Xcode Cloud; гибрид — стеки A/B/C.
  6. Читать далее: pipeline Archive, Flutter Runner, governance swap памяти, codesign — ссылки в конце статьи.
CI аренды bare metal Xcode — выделенный M4 runner с прогретым DerivedData
Один и тот же Flutter iOS: холодный archive на общем VPS часто 18–22 мин; выделенный M4 bare metal + горячий DerivedData — 6–8 мин.

Почему сборки Xcode кажутся медленными — и почему винят не тот слой

При разговоре об оптимизации сборки Xcode всплывают RAM, -jobs и флаги Swift. В реальных iOS/Flutter pipeline разброс xcodebuild archive определяется возможностью переиспользовать контекст выполнения: путь DerivedData, индексированный граф CocoaPods, пересоздание Keychain, конкуренция за inode на релизной неделе.

Если локальные 8 минут становятся 20 на GitHub Actions, Apple Silicon не стал медленнее — CI трактует машину как одноразовую среду: холодный checkout, повторное разрешение pod, импорт сертификата каждый run. На общем Mac VPS добавляются соседи по CPU/IO, вытеснение кэша и ночные бэкапы.

  • Миф 1: крутить -jobs, игнорируя дрейф пути DerivedData.
  • Миф 2: сравнивать один холодный CI с локалью без медианы warm path.
  • Миф 3: низкая месячная цена VPS = полная стоимость cloud Mac.
  • Миф 4: масштабирование на релизе без фиксации Xcode/Ruby/CocoaPods.
  • Миф 5: симулятор + archive на 16 ГБ — swap удваивает время.

Тезис: аренда bare metal продуктизирует переиспользуемый локальный контекст — выделенный M4, квота диска, SSH runner, тёплый DerivedData, при необходимости второй узел — медиана warm archive около трети от холодного CI (≈3x), не магические флаги.

Три столпа ускорения bare metal 3x

3x — та же ветка, тот же Podfile.lock, Release archive, медиана warm path против базы «холодный GitHub Actions + общий VPS». Столпы взаимозависимы.

Столп 1: выделенный bare metal M4 (не общий VPS)

Физическая эксклюзивность: CPU, полоса памяти и запись на SSD без соседей. В контракте: arm64, фиксированный DEVELOPER_DIR, долгосрочный mount DerivedData.

Столп 2: тёплый DerivedData + фиксированные пути

DerivedData — не опциональный кэш. Случайные temp или clean: 8 мин warm → 18 мин cold. Создайте /Users/ci/DerivedData/AppName, укажите -derivedDataPath, запретите лишний flutter clean на релизе.

Столп 3: параллельные узлы (сборка vs тест)

Второй узел — для параллелизма: archive/codesign отдельно, XCTest/симулятор отдельно. Избегает swap на 16 ГБ. >15 сборок/день: второй M4 по дням часто выгоднее 24 ГБ на одной машине.

Пять поверхностей: Entry / Execution / Context / Cost / Permission

Для закупки и архитектурного ревью. Entry — порог входа; Execution — предсказуемость archive; Context — персистентность DerivedData/Keychain/диска; Cost; Permission — сертификаты и сеть.

Поверхность Entry Execution Context Cost Permission
Локальный MacBook Нулевой порог при своём железе Быстрый warm; поездки/выключение DerivedData на месте; личный Keychain Sunk cost; сложно параллелить Свобода сертификатов; слабый аудит
GitHub Actions hosted Старт по YAML Холодная вариативность; очередь Эфемерный контекст; cache miss Поминутная оплата Bootstrap подписи каждый run
Общий Mac VPS Низкая месячная цена Непредсказуемо; соседи DerivedData часто стирают Дёшево на бумаге; скрытое ожидание SSH есть; эксклюзивность не гарантирована
Аренда bare metal (M4 выделенный) Дневной PoC + SSH Стабильный warm archive; scale-out DerivedData/Keychain долго живут Гибко день/неделя; ROI на релизе Self-hosted runner; контроль сертификатов
Xcode Cloud Интеграция Apple Стандартные pipeline; мало кастома Кэши Apple Оплата compute Глубокая интеграция ASC

Большинство «CI в 3 раза медленнее» — ноль в Context, а не нехватка CPU.

Cold vs warm: бенчмарки archive (пример)

Пример: среднее Flutter iOS (~180 файлов Swift/ObjC, 12 локальных Pod), Xcode 16.x, Release archive + IPA. Минуты — медиана десяти прогонов.

Среда Cold archive Warm DerivedData archive Заметки
Локальный M4 MacBook Pro 16 ГБ11.27.4Личный Keychain
GitHub Actions macos-1421.814.6Кэш чувствителен к path/key
Общий Mac VPS (4 vCPU на витрине)19.513.1+30% при IO соседа
Выделенный M4 bare metal (один узел)12.06.8Фиксированный derivedDataPath
Bare metal dual node6.8 wall time (параллельно)Archive и XCTest на разных хостах

Против 21,8 мин холодного hosting 6,8 мин warm bare metal ≈ 3,2x. Ежедневный clean DerivedData возвращает к cold — оптимизируется контекст.

Матрица: нужен ли bare metal runner?

Пять профилей — при двух и более «bare metal first» недельный дневной PoC с медианой warm.

Профиль Сборок/день Сложность подписи Рекомендация Почему
Соло-разработчик<3/деньОдин сертификатЛокальный MacBookКонтекст уже локально
Малая Flutter-команда5–15/деньMulti-flavor + PodBare metal + self-hosted runnerWarm DerivedData даёт максимум
Аутсорс, параллельные проектыПик 30+/деньНесколько Team IDDual node bare metalРазделить build/test
Регулируемый финтех/медСреднеHSM/аудитBare metal + изоляция сетиНужен контроль Permission
Чистая Apple-командаНизкоASC интеграцияXcode Cloud или локальноДостаточно при малом кастоме

Рекомендуемые стеки A / B / C

Три уровня зрелости — неделя пилота A, затем B/C.

Стек A: hosted CI + гигиена путей

Остаться на GitHub Actions с -derivedDataPath, pod install --deployment, раздельными job подписи, concurrency. <5 сборок/день. 20–35% экономии, редко 3x.

Стек B: один self-hosted bare metal runner

Аренда M4, launchd runner, DerivedData и Pods на одном SSD, триггер GitHub/GitLab. Статьи Flutter Runner и codesign для Keychain. Стабильный релизный ритм.

Стек C: dual node + archive-специалист (релизная неделя)

Основной узел warm archive; вторичный — тесты и нотаризация. Третий дневной узел для hotfix. Статьи Archive и swap памяти.

Ловушки, которые bare metal не исправит

  • flutter clean или удаление DerivedData каждый CI.
  • Незакоммиченный Podfile.lock.
  • brew upgrade Xcode на runner в релизную неделю.
  • 16 ГБ: симулятор + archive — swap x2.
  • Неидемпотентный импорт сертификатов.
  • Сравнение одного лучшего run вместо медианы десяти.

Чеклист из 7 шагов

  1. Базовая линия: десять archive с таймингом этапов.
  2. Фиксировать пути: постоянные DerivedData и Pods.
  3. Дневной PoC: M4, десять одинаковых workflow, медиана warm.
  4. Подпись: CI-пользователь и Keychain по статье codesign.
  5. Параллель: второй узел или сдвиг cron.
  6. Governance: алерты disk/inode и swap.
  7. Закупка: ROI, затем неделя/месяц.

FAQ

Хватит ли флагов компилятора для 3x?

Вряд ли. Инкрементальная компиляция Swift, кэш модулей и линковка доминируют.

Чем bare metal отличается от cloud Mac?

Cloud Mac — категория. Подтвердите физическую эксклюзивность, arm64, квоту диска, долгий DerivedData.

Разве cache GitHub Actions не хватит?

Помогает, но не заменяет горячее состояние SSD. Self-hosted bare metal ближе к локали.

Xcode Cloud проще?

Если ASC-центрично и мало кастома — да. Иначе гибче self-hosted bare metal.

Хватит 16 ГБ?

Для одного archive часто да; параллельные симуляторы — 24 ГБ или dual node.

Когда виден ROI?

>8 сборок/день и +12 мин ожидания — часто ясно за неделю PoC.

Итог

Правильная история оптимизации Xcode — сохранять контекст выполнения. Выделенный M4 bare metal + тёплый DerivedData + второй узел ≈ 3x warm archive против холодного CI.

  • Сначала колонка Context, потом покупка CPU.
  • Закупка по медиане warm из десяти прогонов.
  • Стек B для большинства; C на релизе.

Дальше: недельный PoC по 7 шагам и связка статей кластера Archive, Flutter, память, подпись.

Нужны предварительно прогреваемые M4 bare metal runner'ы?

kvmboot — выделенный Apple Silicon bare metal по дням/неделям/месяцам для Xcode archive и Flutter iOS CI.

Тарифы и цены · Детали биллинга · Что такое Cloud Mac