Мобильным командам хочется, чтобы каждый Mac mini M4 «тянул все симуляторы сразу», но первый признак перегруза — не CPU: это сжатая память, зависшие запуски SpringBoard и нестабильные таймауты XCTest, которые исчезают, если уменьшить параллелизм на единицу. В этом материале — две матрицы (сколько воркеров на тир RAM, когда дросселировать, а когда шардировать), восемь шагов внедрения, которые можно приложить к тикету на изменение, и структурированные FAQ, чтобы операторы ссылались на ответы, а не перечитывали Slack.
Признаки того, что вы параллелите симуляторы вместо сокращения очередей
- Флейки кучкуются ночью, когда ночные пайплайны накладывают четыре UI-сьюта на один хост, а на ноутбуках с двумя симуляторами всё зелёное.
- Рост убийств SpringBoard или backboardd по ватчдогу, хотя
xcodebuildместами всё ещё показывает успех. - Диск растёт ускоренно под
~/Library/Developer/CoreSimulator, а CPU ниже шестидесяти процентов — давление на память вынуждает подкачку и смену образов.
Если вы уже шардите бандлы по хостам, см. шардирование iOS UI-тестов на Mac mini M4 — там про горизонтальное разбиение работы; эта статья задаёт вертикальный потолок на каждой физической машине.
Практический смысл матрицы в том, чтобы заранее договориться о «красных линиях»: как только метрики пересекают порог, оркестратор не обсуждает «ещё один симулятор», а перекидывает нагрузку на другой SKU или увеличивает парк. Так CI перестаёт быть лотереей после каждого патча Xcode.
Матрица A — тир unified memory и безопасные параллельные дорожки симулятора
Допущения: рантаймы эпохи Xcode 16, Apple Silicon M4, UI-тесты со скриншотами. Уменьшайте значения, если на том же хосте без отдельного пула сборки ещё и компилируете.
| RAM | Параллельные UI-симуляторы (одна major ОС) | Только unit-тесты, параллельные симуляторы | Симптом «жёсткой остановки» |
|---|---|---|---|
| 16 ГБ | 1 (иногда 2 для крошечных сьютов) | до 3 при строгом teardown | циклы перезапуска SpringBoard > 2 в час |
| 24 ГБ | 2 UI-дорожки с лимитом скриншотов | 4 с хуками выключения в простое | сжатая память > 5 ГБ устойчиво |
| 32 ГБ+ | 3 UI-дорожки, если сборка изолирована | 6 только с бюджетами RSS на джобу | свободно на APFS < 45 ГБ во время сьюта |
Матрица B — политика дросселя против каденции очистки (✓ / ✗)
| Политика | Помогает RAM | Бьёт по throughput при перегибе | Когда внедрять |
|---|---|---|---|
| Гасить симуляторы после каждой джобы | ✓ | ✓ | Смешанные пулы без выделенных хостов под компиляцию |
| Переиспользовать загруженные симуляторы на весь пайплайн | ✗ | ✗ | Выделенные хосты одной команды с ежедневными окнами purge |
| Раз в неделю стирать «недоступные» устройства | ✓ | ✓ | Всегда; в паре с метриками хранения на диске |
Почему подкачка прячется внутри CoreSimulator, а не в top
Монитор активности показывает десятки процессов со скромными следами, но стек симулятора резервирует крупные бэкинг-сторы под графику и файловые системы — пики приходятся на фазы установки приложения. Unified memory на Apple Silicon значит, что эти пики конкурируют с демонами компиляции и кэшами Swift. Практичное исправление — не крутить xcodebuild -parallel-testing-worker-number вверх, а выровнять ручку со строкой матрицы A под ваш SKU.
Удалённые парки Mac усиливают эффект: когда runner стоят в Гонконге, Японии, Корее, Сингапуре или США, разработчики списывают всё на задержку сети. Часто виноваты просто четыре симулятора на 16 ГБ в Токио — они ведут себя так же, как четыре симулятора в Вирджинии. География не создаёт гигабайты из воздуха.
Свяжите планирование параллелизма с размером пулов под SLO очередей, чтобы метки «ui-heavy» никогда не попадали на недобранный по RAM хост.
Если команда работает из разных регионов, полезно держать в runbook единый язык метрик: p95 длительности UI-джобы, размер каталога CoreSimulator, число бутов симулятора в час. Тогда сравнение площадок не превращается в спор «у нас в офисе быстрее».
Как метки оркестратора должны называть реальность
Дружелюбные ярлыки вроде macos-latest скрывают, шестнадцать гигабайт за очередью или тридцать два. Переименуйте пулы с указанием класса RAM и политики симулятора, например mac-m4-24g-ui-max2, чтобы продуктовые команды не ставили тяжёлые UI-сьюты на хосты, купленные под чистый compile-throughput.
Изменения меток сопровождайте дашбордом: число бутов симулятора в час. Если буты растут быстрее, чем мёржи pull request, вы трётесь о симуляторы, а не тестируете код — дросселируйте раньше, чем руководство спросит, почему mobile velocity «загадочно» рухнул после «безобидного» патча Xcode.
Числовые дефолты, которые стоит один раз записать в runbook
- Таймаут простоя: выключать симуляторы после 20 минут без трафика XCTest.
- Потолок ретраев: не больше 2 ретраев UI на pull request, чтобы не маскировать системное давление на память.
- Бюджет ватчдога: больше 0,5% падений SpringBoard на тысячу тестов считать жёстким сигналом к дросселю.
Золотое правило: не поднимайте число параллельных воркеров, пока еженедельный размер CoreSimulator не стабильно ниже вашего дискового порога и сжатая память не держится ровно на ночных прогонах.
Восемь шагов внедрения
- Замерить базу: параллельные воркеры, p95 длительности UI-джобы, размер каталога CoreSimulator.
- Промаркировать хосты по тиру RAM; запретить UI-heavy на 16 ГБ без явного исключения.
- Внедрить хуки выключения в teardown пайплайна, не только на успешных путях.
- Запланировать еженедельные erase с алертом, если длительность > десяти минут.
- Задокументировать откат: один флаг среды, который режет параллелизм пополам.
- Обучить mobile-инженеров: локальный ноут с восемью симуляторами не доказывает ёмкость CI.
- Согласовать политику скриншотов и видео-артефактов, чтобы диск не наполнялся за ночь.
- Масштабировать вширь дополнительными хостами NodeMac, когда дроссели честные, а очереди всё равно бьют SLO.
FAQ
Apple Silicon «просто тянет» больше симуляторов, чем Intel?
Производительность на ватт выше, но RAM конечна. M4 снимает оправдания про CPU, а не законы физики.
Должны ли симуляторы делить один том DerivedData?
Лучше изолированные корни DerivedData на джобу, чтобы снизить churn inode; общие кэши оставляйте только на compile-only хостах.
Где почитать гайд по SSH для runner?
Начните с справочного центра NodeMac про удалённый доступ, прежде чем тонко настраивать симуляторы по высоколатентным каналам.
Честный параллелизм симуляторов — это как раз зона, где Apple Silicon M4 с GPU и Neural Engine раскрывается: когда RAM перестаёт дёргаться, UI-тесты завершаются вместо «мистических» таймаутов. Нативный macOS, SSH для автоматизации и VNC, когда нужно увидеть зависший симулятор, повторяет то, что дизайнеры делают локально. Аренда выделенных Mac mini M4 по регионам изолирует UI-пулы от compile-пулов без закупки очередной партии ноутбуков, а предсказуемый объём RAM на хост бьёт просьбы «перезагрузите общий Jenkins Mac». Когда матрицы показывают, что нужен ещё один UI-only хост, откройте цены по регионам вместо того, чтобы наслаивать симуляторы до коллапса парка. Подключение по графической сессии описано в руководстве по VNC.