Les équipes mobiles qui louent des Mac mini M4 pour des pipelines Xcode perdent souvent des heures à cause d’un mauvais -jobs, d’une contention sur le SSD interne ou d’un RTT inter-régions vers Git et les caches d’artefacts. Cette note propose une matrice décisionnelle : comment le parallélisme de compilation se mappe sur la mémoire unifiée, comment placer le Derived Data sur un volume APFS externe dédié, quand les plafonds I/O et thermiques limitent le débit, et comment choisir un nœud au Japon, en Corée du Sud, à Hong Kong, à Singapour ou sur la côte ouest des États-Unis selon votre plan de données. Croisez-la avec l’article régions, latence, batch et TCO et le guide SSH / VNC — première configuration ; pour les gros artefacts et l’espace APFS, voir aussi téléchargements datasets et matrice régionale.
Trois modes d’échec fréquents dans les tickets :
- Falaises de mémoire unifiée — des jobs clang supplémentaires poussent le RSS du linker vers la compression.
- Derived Data sur volume de démarrage — indexation et intermédiaires Swift se disputent les IOPS avec le système.
- I/O et thermique — des rafales d’écritures aléatoires imposent une modulation d’horloge si le parallélisme n’est pas plafonné.
Parallélisme de compilation et pics mémoire
Traitez xcodebuild -jobs N comme un plafond, pas comme une cible. Partez du nombre de cœurs performance, puis soustrayez une marge pour l’indexation Swift et les lanceurs de tests. Le tableau ci-dessous est un point de départ — validez avec votre schéma le plus lourd.
| Profil d’hôte | Démarrer -jobs | Signal de pic RAM | Quand ajuster |
|---|---|---|---|
| M4 16 Go, CI schéma unique | 4–6 | Pression mémoire jaune en moins de dix minutes | Réduire de deux jobs ou désactiver les paquets de tests parallèles pendant la compilation. |
| M4 16 Go, gros mix ObjC + Swift | 3–4 | Pic de jeu résident du linker vers 12–14 Go | Sérialiser les links ou scinder les cibles ; viser le palier 24 Go. |
| M4 24 Go, appli modulaire | 6–8 | Pression soutenue verte | Augmenter seulement si le Derived Data externe garde le volume de boot sous ~70 % d’occupation disque utile. |
| M4 24 Go, monorepo avec templates lourds | 5–7 | Jaune ponctuel pendant les unity builds | Plafonner séparément les tâches frontend Swift concurrentes si exposé dans les réglages de build. |
Repères à figer dans le runbook : conserver au moins 15 % d’espace libre APFS sur le volume Derived Data ; suspendre toute montée de -jobs si la pression mémoire reste jaune plus que quelques minutes.
Derived Data externe : chemin, montage SSD et paramètres APFS
Branchez un boîtier NVMe rapide (USB4 ou classe Thunderbolt) et dédiez un volume APFS au Derived Data. N’activez un APFS sensible à la casse que si vos dépôts le supposent déjà — un décalage provoque des boucles de rebuild difficiles à diagnostiquer.
Paramètres APFS à documenter : rôle du volume (APFS simple, chiffré ou non), allocation « un SSD = un volume CI » pour limiter la fragmentation des métadonnées, et désactivation des instantanés sur ce volume si les copies en arrière-plan gênent les builds nocturnes. Après branchement, vérifiez le montage automatique (Utilitaire de disque ou script d’orchestration) pour que le chemin reste identique à chaque session.
export DERIVED_DATA_PATH=/Volumes/XcodeDerived/DD
xcodebuild -derivedDataPath "$DERIVED_DATA_PATH" -jobs 6 …
Checklist permissions : l’utilisateur CI possède le point de montage ; évitez chmod 777. Sur hôtes mutualisés, utilisez des dossiers par branche ou par locataire et purgez après fusion.
- Valider le boîtier avec une sonde d’écriture séquentielle d’environ une minute.
- Créer le volume APFS et noter la sensibilité à la casse dans le wiki.
- Montage au démarrage ou via l’orchestrateur avec le même chemin à chaque fois.
- Exporter DERIVED_DATA_PATH dans l’environnement de l’agent.
- Nettoyer une fois après migration, reconstruire avec un -jobs bas, puis remonter progressivement.
Quota I/O et seuils de « refroidissement » (thermique + charge disque)
Lorsque les percentiles de latence disque s’élargissent ou que la fréquence CPU oscille, vous êtes limité par l’I/O ou la thermique — pas par le calcul pur. Le tableau suivant sert de seuils d’alerte pour l’automatisation ou la garde humaine pendant la phase de rodage.
| Signal | Seuil indicatif | Atténuation |
|---|---|---|
| Profondeur de file du volume externe | Saturation soutenue trois à cinq minutes | Réduire -jobs d’une unité ; décaler les cibles très linker-heavy. |
| Utilisation du SSD interne | Au-delà d’environ 70 % « occupé » pendant la compilation | Déporter davantage d’intermédiaires hors du boot ; désactiver Time Machine pendant les jobs. |
| Tendance température du package CPU | Oscillation rapide avec abaissement d’horloge | Baisser le parallélisme pendant une vingtaine de minutes ; vérifier l’entrée d’air sur la photo rack fournie par l’hébergeur. |
| Récupération réseau vers cache | RTT élevé + fenêtres TCP modestes | Colocaliser le runner avec la région des artefacts ; voir la section régions ci-dessous. |
Japon, Corée du Sud, Hong Kong, Singapour vs côte ouest US : arbitrage des nœuds
Choisissez la région où vivent surtout votre dépôt Git distant, votre cache binaire et la sortie vers la notarisation. Bandes de RTT illustratives depuis des équipes produit continentales (votre mesure dépend du FAI et du peering) :
| Région du runner | RTT typique vs stockage objet Tokyo | RTT typique vs hébergeur de code US Ouest |
|---|---|---|
| Tokyo | 1–5 ms (même métro) | 110–150 ms |
| Séoul | 25–40 ms | 130–170 ms |
| Hong Kong | 35–55 ms | 140–180 ms |
| Singapour | 65–90 ms | 160–200 ms |
| US Ouest | 120–160 ms | 1–8 ms (même métro) |
Repères coût location (jour / mois) : les créneaux à la journée conviennent aux pics de release et au rodage matériel ; lorsque vous enchaînez plus de huit à dix jours de build contigus par mois, un engagement mensuel lisse en général le coût unitaire. Dimensionnez le SKU sur le scénario pire cas (jobs nocturnes, gros pull LFS), pas sur la moyenne des builds de midi. Les grilles et suppléments stockage sont listés sur Tarifs (le cadre TCO inter-régions est rappelé en tête d’article).
FAQ : échecs, nouvelles tentatives et pièges distants
Linker tué ou code de sortie 137. Manque de mémoire — baissez -jobs, arrêtez les services Simulateur inutiles ou passez au palier 24 Go.
Erreurs « I/O » intermittentes sur le volume Derived Data. Contrôlez câble et remontage, espace libre APFS, nettoyez le dossier du schéma concerné, reconstruisez une fois avec -jobs 1, puis rétablissez le parallélisme.
Signature de code OK en local mais échec sur l’hôte loué. Comparez partition de trousseau, réglages security et identités non interactives pour l’automatisation.
Timeouts Git LFS ou résolution SPM. La région du runner ne correspond pas au magasin de blobs ; mettez en cache dans la même zone ou rapprochez le nœud selon le tableau ci-dessus.
Pourquoi mon -jobs « optimal » change après une mise à jour Xcode ? Les chaînes d’outils et le linker évoluent ; refaites une courbe de cinq builds avec surveillance mémoire à chaque bump majeur.
Synthèse
Xcode sur M4 loué récompense un réglage -jobs prudent, un volume APFS Derived Data dédié sur SSD externe rapide et des garde-fous I/O et thermiques explicites. Alignez la région du nœud sur vos sources et caches ; utilisez la location à la journée pour les pics courts et le forfait mensuel pour une charge de compilation régulière.