Сколько Mac mini M4 нужно для сборки? Алгоритм ёмкости команды 2026

У Apple Xcode есть встроенный отчёт о времени сборки, а официальная документация отдельно описывает зависимости целей и параллельное выполнение задач (методика Apple для Build Timing Summary). Поэтому количество Mac mini M4 нельзя выводить из числа разработчиков, ядер процессора или средней месячной загрузки. Для планирования ёмкости сборок на Mac mini M4 нужны четыре входа: пиковый поток задач, P95 длительности по типам, допустимое ожидание и резерв на сбои. Сначала измерьте их на реальном проекте, затем считайте узлы и округляйте результат вверх.

Эта статья предназначена:

  • IT-руководителям, которые формируют бюджет Mac-инфраструктуры для новой iOS-команды;
  • руководителям инженерной эффективности, у которых очередь уже задерживает слияние изменений или релизы;
  • CTO и техническим директорам, выбирающим между покупкой фиксированного пула, арендой удалённого Mac и гибридной схемой.

Поток задач в пиковом интервале

Сначала определите не число сотрудников, а количество заданий, поступающих в CI за короткий интервал. Отдельно учитываются проверки pull request, ночные задания, UI-тесты и архивирование для публикации.

Месячное среднее здесь мало полезно. Десять спокойных часов не компенсируют короткое окно, в котором одновременно запускаются проверки после массового слияния, плановые тесты и релизная сборка.

Для каждого интервала фиксируются:

  • время начала и окончания;
  • число поступивших задач;
  • число завершённых задач;
  • тип каждой задачи;
  • отменённые, повторённые и завершившиеся ошибкой задания;
  • время ожидания до фактического запуска.

Если CI собирает только общий счётчик, его необходимо дополнить метками задания. В противном случае тяжёлый Archive будет неразличим среди коротких проверок, а среднее значение исказит расчёт.

P95 длительности

Для каждого типа работы берётся P95, а не среднее время. Это означает, что показатель должен отражать длинный хвост реальных запусков: крупный pull request, холодный кэш, изменившийся набор зависимостей или дополнительный тестовый сценарий.

P95 нужно считать отдельно для:

  • статического анализа и проверки проекта;
  • инкрементальной компиляции;
  • полного или холодного построения;
  • unit-тестов;
  • UI-тестов;
  • Archive, подписи и подготовки артефакта.

Xcode позволяет анализировать временные показатели сборки, а Apple рекомендует использовать данные о фазах и зависимостях, а не оценивать проект по одной общей цифре. В документации также описаны состав Build Phases и способы выявления медленных участков.

Целевое ожидание

До покупки оборудования зафиксируйте, сколько времени задача может находиться в очереди. Для проверки pull request, ночного запуска и релизного Archive это обычно разные политики. Нельзя применять один порог ко всем рабочим процессам.

В расчёте используется переменная (W_{target}) — допустимое ожидание. Фактическое значение должно быть записано в правилах CI и проверяться по журналам. Если цель не определена, вопрос «сколько Mac mini M4 нужно» не имеет проверяемого ответа: любое число будет только предположением.

Резерв и прерывания

Производственный пул не должен работать на пределе. В резерв входят:

  • плановое обслуживание;
  • обновление Xcode и macOS;
  • недоступность хоста;
  • повторный запуск после сбоя;
  • пик релизных задач;
  • временная потеря доступа к зависимостям или внутренней сети.

Резервная машина не должна одновременно считаться частью обычной полной загрузки. Иначе при первом отказе очередь станет штатным режимом работы.

Один «средний билд» не описывает iOS CI/CD. Проверка pull request может быть короткой и инкрементальной, а Archive — длительным, с подписью, упаковкой и загрузкой артефактов. UI-тесты дополнительно занимают симуляторы и создают другой профиль нагрузки.

Для каждого типа задания рассчитайте трудоёмкость:

[ V_i = \lambda_i \times P95_i ]

где:

  • (\lambda_i) — число задач типа (i) за выбранный пиковый интервал;
  • (P95_i) — P95 времени выполнения этого типа;
  • (V_i) — объём работы в единицах времени узла.

Суммарный поток:

[ V_{peak} = \sum V_i ]

Если в одном окне накладываются pull request, расписание ночных тестов и релиз, их объёмы складываются. Нельзя вычитать ночные задания только потому, что они формально запланированы: если они пересекаются с рабочим пиком, они потребляют ту же ёмкость.

Источник данных

Журналы должны включать идентификатор коммита, версию Xcode, тип задания, состояние кэша и время на каждом существенном этапе. Минимальный набор для анализа:

  • время постановки в очередь;
  • время назначения runner;
  • начало и конец сборки;
  • начало и конец тестов;
  • этап Archive и подписи;
  • результат;
  • причина повторного запуска.

Для маршрутизации полезно разделять runner по меткам и группам. Такая модель описана в официальной документации GitHub Actions о labels self-hosted runner. Сам принцип применим и к другим CI-системам: тяжёлые Archive не должны случайно попадать на узел, предназначенный для быстрых проверок.

Аппаратные характеристики Mac mini M4 и Mac mini M4 Pro задают допустимые конфигурации, но не превращаются напрямую в число сборок в час. Их можно сверить на официальной странице технических характеристик Mac mini, однако итоговая производительность зависит от проекта, скриптов, зависимостей, кэша и степени параллелизма.

Бенчмарк проводится на том же коде и с теми же настройками, которые будут использоваться в производстве.

  1. Зафиксируйте commit или тег проекта.
  2. Установите точную версию Xcode и macOS.
  3. Зафиксируйте версии Swift Package Manager, CocoaPods или иных источников зависимостей.
  4. Очистите DerivedData для холодного прогона.
  5. Повторите запуск с сохранённым кэшем для инкрементального сценария.
  6. Отдельно выполните unit-тесты и UI-тесты.
  7. Выполните Archive с теми же профилями подписи.
  8. Сохраните команду запуска, логи и итоговые временные показатели.
  9. Повторите каждый профиль в несколько независимых циклов.
  10. Сравните P95, ошибки и разброс, а не только самый быстрый запуск.

Количество повторов должно быть установлено внутренним регламентом измерений. Важно не подставлять произвольное число прогонов в модель: оно должно быть одинаковым при сравнении конфигураций.

При анализе Xcode Build Timing Summary ищите последовательные скрипты, лишние зависимости между целями и этапы, которые не могут выполняться параллельно. Apple отдельно описывает настройку схем проекта и зависимости целей. Если узел тратит время на ненужную работу, покупка ещё одного узла лишь масштабирует неэффективность.

Пропускная способность

Обозначьте измеренную эффективную производительность одного узла как (C_{node}). Она рассчитывается из того же состава задач, который используется для (V_{peak}):

[ C_{node} = \frac{\text{полезный объём завершённых задач}}{\text{интервал измерения}} ]

В понятие «полезный объём» не следует включать отменённые задания, повторные запуски из-за неверной конфигурации или сборки, выполненные с другой версией зависимостей. Если набор задач изменился, старый показатель нельзя переносить в новый бюджет.

Базовое количество рабочих узлов:

[ N_{base} = \left\lceil \frac{V_{peak}}{C_{node}} \right\rceil ]

Округление выполняется вверх. Дробный узел не существует, а округление вниз превращает дефицит мощности в очередь.

Для целевого ожидания вводится дополнительная проверка. Если при (N_{base}) очередь превышает (W_{target}), количество узлов увеличивается до тех пор, пока фактический P95 ожидания не укладывается в установленную политику. Простого деления иногда недостаточно: задачи могут приходить неравномерно, а тяжёлые Archive — блокировать ограниченные ресурсы.

Сервисные режимы обычно различаются так:

  • ночные сборки — допускают более длинное ожидание, если оно не влияет на утренний результат;
  • ежедневная проверка изменений — требует предсказуемого запуска, иначе разработчики ждут обратную связь по pull request;
  • релизное окно — требует отдельной ёмкости и резерва, поскольку задержка одной цепочки может сдвинуть публикацию.

Решение об увеличении пула принимается по устойчивому превышению цели в нескольких сопоставимых пиковых интервалах. Единичный пик CPU не является достаточным основанием. Сначала проверяются:

  • неправильные labels и маршрутизация;
  • зависшие runner;
  • повторные задания;
  • блокировки ресурсов;
  • медленные скрипты;
  • недоступный кэш;
  • внешние зависимости;
  • ошибки подписи.

Уровень загрузки

Процент загрузки — диагностический показатель, а не самостоятельное правило покупки. Средняя загрузка 50 % может скрывать очередь в релизное окно. Высокая загрузка также может быть нормальной для ночной очереди, если она не нарушает SLA.

Для принятия решения отслеживаются одновременно:

  • P95 времени ожидания;
  • P95 полного времени выполнения;
  • длина очереди в пиковые интервалы;
  • доля отменённых и повторных запусков;
  • доступная ёмкость после вывода одного узла;
  • время восстановления после сбоя.

Если очередь выходит за пределы цели, а причина находится в реальном дефиците (C_{node}), расширение оправдано. Если очередь вызвана последовательным скриптом, сначала меняется pipeline.

Один Mac mini M4 может выполнять несколько заданий, но число слотов нельзя назначать по количеству CPU-ядер. Параллельные процессы делят память, дисковую подсистему, DerivedData, симуляторы и сеть. В результате два задания могут выполняться дольше, чем по одному, а суммарная пропускная способность окажется ниже ожидаемой.

Особенно внимательно проверяются:

  • общий каталог DerivedData;
  • одновременный запуск симуляторов;
  • временные каталоги сборки;
  • Keychain и профили подписи;
  • рабочие каталоги разных веток;
  • кэш зависимостей;
  • доступ к приватным репозиториям;
  • очистка после сбоя.

Общий Keychain между независимыми командами создаёт не только конкуренцию, но и риск раскрытия сертификатов. Совместный DerivedData может привести к трудно воспроизводимым ошибкам, если задания используют разные commit или версии зависимостей.

Один узел с несколькими слотами

Преимущество — меньшее количество хостов и более простое управление. Недостатки:

  • один сбой выводит из работы несколько заданий;
  • сложнее гарантировать очистку среды;
  • конкуренция за память и дисковый ввод-вывод;
  • сложнее отделить релизные ключи;
  • обновление узла затрагивает больше pipeline.

Несколько узлов с одним основным заданием

Преимущество — меньший домен отказа и более предсказуемая изоляция. Недостатки:

  • выше операционные расходы;
  • нужно поддерживать одинаковые образы и версии;
  • часть ресурсов может простаивать вне пика;
  • требуется корректная маршрутизация.

Допустимый параллелизм определяется только собственным стресс-тестом или воспроизводимым тестом поставщика. В отчёте должны быть указаны конфигурация, версия Xcode, состояние кэша, состав заданий, очередь, P95 и ошибки. Без этих данных утверждение «один Mac mini M4 одновременно запускает N сборок» нельзя считать доказанным.

Планирование команды

Небольшой непроизводственный проект может начать с одного узла, если очередь не нарушает целевое ожидание, а отказ не блокирует релиз. Для стабильной рабочей нагрузки нужны базовый пул и отдельный резерв. Для критичного релизного процесса чаще подходит фиксированная ёмкость с дополнительным удалённым Mac на период пика.

Очередь как основание расчёта

Сначала вычисляется объём работы за пик, затем измеряется эффективная производительность узла. После этого проверяется симуляция или фактический журнал очереди. Если базовое количество узлов не выдерживает (W_{target}), добавляется ёмкость. Усреднение по дню или месяцу без пикового разреза скрывает дефицит.

Одновременные задания Xcode

Вместо фиксированного лимита устанавливается экспериментальный предел. Запускаются независимые задания с одинаковым commit и одинаковым состоянием зависимостей. Пределом становится режим, в котором P95 времени, ошибки и очередь остаются приемлемыми. Отдельно тестируются Archive и UI-тесты: они создают другой профиль нагрузки.

Мощность против количества узлов

Если проблема находится внутри одной последовательной сборки, более мощный Mac может сократить время задачи. Если проблема состоит в большом количестве независимых задач, дополнительные узлы обычно дают более прямой эффект. Сравнивать нужно стоимость единицы полезной пропускной способности и поведение при отказе, а не только время одного успешного запуска.

Момент расширения

Расширение начинается не при достижении условного процента CPU, а при систематическом нарушении целевого времени очереди. Перед этим исключаются ошибки планировщика, зависшие runner, неэффективные Build Phases и повторные запуски. После исправлений снова измеряются поток задач и P95. Только затем обновляется формула количества узлов.

Следующий список превращает расчёт в проверяемое решение. Каждый пункт должен иметь владельца и ссылку на исходный журнал или отчёт тестирования.

  • [ ] Выделены пиковые интервалы, а не только средние значения за месяц.
  • [ ] Все задачи разделены на проверки, тесты, Archive и вспомогательные процессы.
  • [ ] Для каждого типа рассчитан P95 времени выполнения.
  • [ ] Зафиксировано целевое время ожидания для рабочего и релизного потока.
  • [ ] Отдельно посчитаны холодные и инкрементальные сборки.
  • [ ] Версия Xcode, macOS, commit и состояние кэша записаны в отчёте.
  • [ ] Измерена эффективная производительность одного узла.
  • [ ] Проверено влияние параллельных слотов на P95 и ошибки.
  • [ ] DerivedData, Keychain, симуляторы и временные каталоги изолированы.
  • [ ] Резерв на обслуживание и отказ не включён в штатную полную загрузку.
  • [ ] Проверены labels, группы runner и правила маршрутизации.
  • [ ] Для Archive предусмотрена отдельная политика приоритета.
  • [ ] Сравнены фиксированный пул, эластичная ёмкость и смешанная схема.
  • [ ] Выполнен контрольный прогон на удалённом Mac с тем же pipeline.
  • [ ] В бюджете учтены восстановление, обновления, хранение артефактов и инженерное сопровождение.

Итоговое число рабочих узлов:

[ N_{total} = N_{base} + N_{reserve} ]

(N_{reserve}) не следует выбирать произвольно. Он должен покрывать конкретные события: плановое обновление, отказ одного хоста, релизный пик или необходимость параллельно проверить новую версию Xcode.

Для финансового решения сравниваются три группы затрат:

  • фиксированная стоимость закупки и владения Mac;
  • стоимость эластичной ёмкости, включая аренду, доступ, хранение и администрирование;
  • потери от ожидания: время разработчиков, задержки слияния, сдвиг релиза и повторные запуски.

Покупка обычно логична при стабильной круглосуточной нагрузке, предсказуемом составе проектов и наличии ресурсов для ремонта, обновлений и физического доступа. Аренда удалённого Mac удобнее, когда пик кратковременный, команда растёт неравномерно или нужно проверить расчёт без немедленной закупки. На странице NOVAKVM для русскоязычных пользователей можно начать с контрольного окружения и прогнать собственный pipeline.

Гибридная схема подходит, когда есть постоянная базовая нагрузка и редкие релизные пики. В ней фиксированный пул обслуживает обычные проверки, а дополнительный удалённый Mac подключается только при приближении очереди к целевому порогу. Это не означает автоматическую экономию: стоимость передачи артефактов, доступа к приватной сети, секретов и сопровождения нужно включить в TCO.

Для команд, которым нужен именно тестовый узел под Mac mini M4, параметры доступа и доставки следует проверять до расчёта. Информация о заказе Mac mini M4 через NOVAKVM должна использоваться только вместе с фактическим тестом проекта, а не как замена измерению производительности.

  1. Выберите один репрезентативный проект и зафиксируйте commit.
  2. Соберите CI-логи за несколько сопоставимых пиковых периодов.
  3. Разделите задания по типу и вычислите P95 длительности.
  4. Проведите холодный и инкрементальный бенчмарк на целевой конфигурации.
  5. Проверьте Build Timing Summary и устраните лишние последовательные этапы.
  6. Измерьте работу одного задания и нескольких независимых слотов.
  7. Рассчитайте (V_{peak}), (C_{node}), (N_{base}) и резерв.
  8. Прогоните нагрузку с реальной маршрутизацией и правилами приоритета.
  9. Установите наблюдение за очередью, P95 ожидания, ошибками и доступностью.
  10. Зафиксируйте условие расширения: устойчивое нарушение цели после устранения конфигурационных причин.

Такой порядок не подменяет измерение рекламными характеристиками. Он также позволяет сравнить M4 и M4 Pro по результату конкретного pipeline, а не по названию чипа.

Если команда оставляет только локально купленные Mac mini, у такого подхода есть реальные ограничения: капитальные затраты возникают до подтверждения нагрузки, резервный узел может простаивать, а обслуживание и замена оборудования ложатся на внутреннюю IT-команду. При резком релизном пике физический пул не расширяется за часы, а перенос CI в другой офис или регион требует отдельной сетевой и секретной инфраструктуры.

Удалённый Mac в NOVAKVM позволяет сначала выполнить тот же набор контрольных задач, получить собственные P95 и подставить их в формулу. Если дневная и релизная нагрузка заметно различаются, фиксированный базовый пул с временной арендой может быть рациональнее закупки максимального количества машин заранее. Но для постоянной тяжёлой нагрузки, требующей физического USB-доступа или полного контроля над устройством, собственные Mac остаются более подходящим вариантом. Решение стоит принимать после заполнения списка измерений, а не по числу разработчиков.

Масштабируйте пул сборки с NOVAKVM

Арендуйте удалённые Mac mini M4 для iOS CI/CD и подберите количество узлов с учётом фактической нагрузки команды.

Используйте выделенные Mac для параллельных сборок, тестирования и изоляции задач без покупки дополнительного оборудования.

Смотреть цены →