Когда одного Mac mini достаточно — и когда нет
Mac mini M4 (10-ядерный CPU, 16 ГБ унифицированной памяти) архивирует средний SwiftUI-проект примерно за четыре минуты — этого хватает инди-разработчикам или небольшим командам с несколькими сборками в день. Проблемы проявляются в трёх типичных сценариях:
Во-первых, матрицы multi-scheme / multi-app: в monorepo нужно собрать основное приложение, Watch, Widget и варианты Debug/Release. Одна машина ставит их в очередь последовательно, и реальное время растёт линейно с числом target'ов. Во-вторых, общие кэши компиляции: передача DerivedData или кэшей SPM с одного runner'а на другие через публичный порт 1 Gbps превращает синхронизацию на гигабайты в минутную «налоговую» задержку. В-третьих, распределённый инференс или рендер-шарды: машины часто обмениваются промежуточными артефактами, и задержка Ethernet плюс лимиты полосы упираются раньше CPU.
Эта статья не о том, стоит ли арендовать Mac в облаке (это на страницах с ценами). Она отвечает на один конкретный вопрос: после связи Thunderbolt 5 в одном узле ЦОД насколько быстрыми становятся пути данных между машинами — и что это значит для реального времени параллельных сборок?
Оборудование: 3 × Mac mini M4 · 10-ядерный CPU · 16 ГБ унифицированной памяти · 256 ГБ NVMe (узел ZovCloud в Японии, одна стойка).
Связь: дополнение Thunderbolt 5 (номинальный физический канал 80 Gbps); базовая линия — выделенный публичный порт 1 Gbps каждой машины.
ОС: macOS 15 Sequoia; инструменты: iperf3 3.17, dd + SMB, xcodebuild 16.4.
Пример проекта: SwiftUI monorepo (~142 тыс. строк, основное приложение + 2 extension + 1 target Watch).
Что на самом деле соединяет связь Thunderbolt 5
Разберём распространённое заблуждение: связь TB5 не сливает три CPU в один «супер-Mac» и не запускает прозрачный распределённый компилятор. Она даёт высокоскоростное физическое соединение между машинами в одном регионе — номинально 80 Gbps, намного выше uplink 1 Gbps каждого хоста.
В ZovCloud связь работает только для инстансов в одном узле дата-центра: Сингапур и Токио нельзя соединить по TB5. После выдачи ЦОД прокладывает кабели Thunderbolt и настраивает мост; macOS показывает дополнительный интерфейс Thunderbolt Bridge / высокоскоростного моста для TCP, SMB/NFS или объектных кэшей.
Модель ценности проста: CPU планируются независимо; стоимость переноса данных между хостами резко падает. Если пайплайн никогда не синхронизирует крупные артефакты между машинами — каждый runner клонирует, собирает и грузит в object storage сам — выгода будет минимальной, и за связь платить не стоит.
Топология и готовность: линк действительно поднят?
Мы использовали треугольник «контроллер + два worker'а»: node-a для планирования и сбора артефактов, node-b / node-c — параллельные сборщики. После оплаты дополнения TB5 (или включения в консоли на работающих инстансах) интерфейсы моста Thunderbolt появились за несколько минут. Перед бенчмарками — три проверки, иначе можно измерять обычный Ethernet.
-
01
Проверить интерфейсы моста
На каждом хосте:
ifconfigили «Системные настройки → Сеть». Должен быть Thunderbolt Bridge (или именованный мост ЦОД) с приватным IP в одной подсети. -
02
Двунаправленный ping и проверка MTU
ping -c 20между всеми парами. RTT — доли миллисекунды до ~1 мс. Джиттер в несколько мс часто означает публичный маршрут — смотрите таблицы маршрутизации. -
03
Закрепить sync-трафик на IP TB
Укажите в скриптах сборки адреса подсети моста, а не публичный IPv4 — чтобы
rsync/ SMB не откатились на uplink 1 Gbps.
Видите только дерево USB4 / Thunderbolt без рабочих IP? Проверьте статус связи «active» в консоли, перезапустите сетевой стек или откройте тикет в поддержку. Связь только в одном узле — между регионами используйте публичный интернет или object storage.
Пропускная способность: TB5 против публичных путей 1 Gbps
Первый раунд: iperf3 для однонаправленного TCP. Базовая линия: публичный IPv4 машин друг с другом (коммутатор в стойке, но лимит порта 1 Gbps). Тестовый путь: приватная подсеть Thunderbolt Bridge. По 60 секунд, три повтора, в отчёт — медиана.
| Путь | Пропускная способность TCP (медиана) | RTT (медиана) | Примечания |
|---|---|---|---|
| Публичный IPv4 | 0,94 Gbps | 0,6–1,2 мс | Ограничено портом 1 Gbps |
| Thunderbolt Bridge | 58,4 Gbps | < 0,3 мс | iperf3 один поток, CPU не насыщена |
| TB5 двунаправленно | 51,2 Gbps up / 49,8 Gbps down | < 0,4 мс | Небольшое падение при dual-stream; всё равно намного выше GbE |
Пользовательский TCP редко достигает теоретических 80 Gbps — накладные расходы протокола и планирование одного потока; наш тест был память-память, без диска. Для практики достаточно «на порядок-два быстрее 1 Gbps», чтобы сменить стратегию синхронизации: многогигабайтные кэши, которые раньше сжимали дельтой, можно передавать целиком — скрипты проще.
Крупные файлы и общие кэши: где выигрывает реальное время
Красивые цифры пропускной способности не ускорят пайплайн, если вы не двигаете большие blob'ы.
Мы синхронизировали снимок DerivedData 8,4 ГБ (Module Cache и промежуточные файлы) по SMB
и забрали .xcarchive 2,1 ГБ на контроллер.
| Задача | Через 1 Gbps публично | Через мост TB5 | Сокращение реального времени |
|---|---|---|---|
| 8,4 ГБ DerivedData → worker | 72 с | 1,5 с | ~48× |
| 2,1 ГБ xcarchive → контроллер | 19 с | 0,4 с | ~47× |
| 1,6 ГБ кэша SPM двунаправленно | 28 с | 0,6 с | ~46× |
Вывод: любой шаг с переносом гигабайтных артефактов между хостами с TB5 сжимает время синхронизации почти до нуля.
Если каждая машина сама делает git clone, тянет зависимости и грузит в object storage без peer-трафика,
ускорение близко к нулю — деньги за связь потрачены зря.
Параллельный Archive: насколько низко может упасть реальное время?
Второй раунд ближе к CI: один commit, три scheme (основное приложение Release, Widget Release, Watch Release) с
xcodebuild archive на отдельном worker'е; базовая линия — три последовательных Archive на одной машине.
Контроллер раздавал снимки исходников по TB5, собирал артефакты и делал лёгкую валидацию. По три прогона на конфигурацию, медиана.
Параллельное реальное время — 4:18, близко к самому медленному одиночному scheme (Archive основного приложения ~4:05) плюс ~9 секунд на push исходников/кэша и pull артефактов. По 1 Gbps одна синхронизация добавляет больше минуты, съедая большую часть выигрыша от параллелизма.
Ускорение не линейное «три машины = 3×». Разная длительность scheme, разблокировка сертификатов и гонки SPM оставляют реальное время на самом медленном звене. Задача TB5 — сжать dispatch и сбор с минут до секунд, чтобы параллельное планирование окупалось; прирост CPU — от нескольких физических хостов, считающих одновременно, а не от кабелей, «магически» ускоряющих однопоточную компиляцию Swift.
Дробить один target между хостами для «распределённой одиночной сборки» в Xcode непрактично и не цель TB5. Правильный паттерн: резать работу по scheme / app / матрице платформ — каждая машина выполняет полную независимую сборку, а быстрая связь снижает стоимость планирования и переноса артефактов.
Подводные камни, с которыми мы столкнулись
1. Скрипты sync привязаны к неверному интерфейсу.
Первый iperf показал «всего 900 Mbps» — скрипты использовали публичные IP. Переход на подсеть моста: сразу выше 50 Gbps.
Явно задайте CLUSTER_IFACE и PEER_TB_IP в переменных CI.
2. Подпись SMB ограничивает пропускную способность.
Стандартный SMB macOS может насытить CPU раньше полосы на быстрых линках. Для коротких бенчмарков настройте подпись;
в продакшене взвесьте безопасность и скорость или используйте rsync по SSH на IP TB для каталогов кэша.
3. Keychain и подпись на каждом хосте. Связь не решает сертификаты. Каждому worker'у нужны Distribution-сертификаты и разблокировка. Мы переиспользовали автоматизацию, но ключи держали на машине — без общего каталога keychain из-за риска порчи при конкуренции.
4. Диск раньше сети. Системные тома 256 ГБ при одновременной записи DerivedData иногда повышали I/O wait. Крупным monorepo с тяжёлыми ночными пакетами стоит сначала добавить расширение SSD +1 ТБ / +2 ТБ, потом — больше связанных узлов; TB5 не поможет, если локальные диски не успевают.
Когда TB5 окупается — и когда можно обойтись без него
Сведите бенчмарки в таблицу решений перед покупкой только из-за «80 Gbps»:
| Ваша ситуация | Рекомендация | TB5 критичен? |
|---|---|---|
| Одно приложение, мало сборок в день | Один выделенный узел | Обычно нет |
| Матрица multi-scheme / ночные пакеты | 2–3 параллельных хоста + контроллер | Да, сильно (чувствительно к sync) |
| Ферма общего DerivedData / SPM | Один источник кэша + несколько worker'ов | Да (sync на гигабайты) |
| Независимые сборки, только upload в object storage | Несколько self-hosted runner'ов | Опционально, ограниченный ROI |
| Межрегионально (напр. Токио + Сингапур) | Object storage / git — не TB5 | Недоступно (только один узел) |
Цены: базовые узлы ZovCloud от $19,8/день, $53,5/неделя, $99,1/месяц, $269,6/квартал; дополнение Thunderbolt 5 от $1,8/день, $4,9/неделя, $9,1/месяц, $24,8/квартал. Три месячных хоста плюс связь подходят командам, чьи очереди явно упираются в sync и последовательные сборки; на неделю релиза можно включить связь посуточно и отключить после тестов — без покупки меди и коммутаторов в ЦОД.
От бенчмарка к продакшену: выделенные облачные кластеры
Три связанных Mac mini в офисе могут дать похожую пропускную способность, но стойка, кабели, отключения питания, фиксированные публичные IP, ротация сертификатов и ночное дежурство — на вас. Для многих mobile-команд настоящий барьер — ops-нагрузка, а не возможность запустить iperf3.
Быстрые mesh'и Linux VM всё равно не проходят «ворота» toolchain Apple: без полного macOS нет легитимного пути
xcodebuild / codesign / TestFlight.
Перепроданные общие macOS-хосты дают джиттер памяти и диска при параллельных сборках, руша «теоретический параллелизм».
ZovCloud держит каждый хост как выделенный физический Mac mini M4 (10 ядер, 16 ГБ, выделенная полоса 1 Gbps, полные права администратора). Когда нужна скорость между хостами, включите связь Thunderbolt 5 в том же регионе для физического канала 80 Gbps; выдача за 1–5 минут после оплаты, регионы: Сингапур, Япония (Токио), Корея (Сеул), Гонконг и восток США. Работают браузерный VNC, SSH и сторонние VNC-клиенты; подключение runner'ов как на одном хосте — добавьте только IP моста для sync.
-
01
Сначала определите параллельное разбиение
По app / scheme / платформе; убедитесь, что у каждой машины независимый target Archive, прежде чем масштабировать кластер.
-
02
Закажите хосты в одном регионе с TB5
На странице заказа выберите несколько инстансов в одном регионе и отметьте Thunderbolt 5; детали — в дополнениях к тарифам.
-
03
Закрепите IP моста, затем подключите runner'ы
После проверки готовности направьте sync кэша и сбор артефактов через подсеть TB; публичный порт оставьте для git, object storage и релизов.
Связь Thunderbolt 5 решает как быстро переносить данные между настоящими Mac — а не как выдать одну машину за три. Когда матричные сборки и sync кэша уже доминируют в реальном времени, выделенные кластеры в одном регионе на 80 Gbps часто выигрывают у более длинных очередей на одном хосте; если у вас одно приложение и редкие релизы, стабильный выделенный узел M4 обычно разумнее.
Нужны параллельные сборки? TB5 80 Gbps по запросу
Выделенные узлы ZovCloud Mac mini M4: полный macOS, 16 ГБ унифицированной памяти, опциональная связь Thunderbolt 5 в том же регионе, доступ SSH / VNC — от $19,8/день, дополнение TB5 от $1,8/день.