Performance 15 avril 2026

2026-04-15 : données dérivées Xcode, TMPDIR et xcresult sur Mac cloud loué (CI)

Équipe ingénierie MacXCode 15 avril 2026 ~13 min

Les équipes mobiles qui louent des Mac mini M4 à Hong Kong, Tokyo, Séoul, Singapour et US Est accusent souvent « Xcode lent » alors que le vrai problème est la contention disque : deux pipelines écrivent la même tranche DerivedData, un job de tests UI remplit /tmp, ou un bundle .xcresult dépasse 6 Go et affame des archives concurrentes. Ce guide daté du 2026-04-15 précise qui a besoin d’isolation par job, recense des défaillances concrètes sur builders SSH sans tête, compare des stratégies dans un tableau, fournit un runbook shell en huit étapes chiffré, et renvoie vers SwiftPM cache & registre et signature auto vs manuelle pour garder des enchaînements déterministes.

Le silicium Apple Silicon nu réduit le bruit CPU, mais le NVMe reste borné. Partager ~/Library/Developer/Xcode/DerivedData par défaut produit des échecs SwiftEmitModule aléatoires et des cartes de modules obsolètes. Lier DERIVED_DATA_PATH, TMPDIR, -resultBundlePath et -clonedSourcePackagesDirPath à un même préfixe de job rend la planification capacitaire honnête lorsque vous comparez des nœuds régionaux.

Qui profite d’un DerivedData par job sur Mac cloud

L’isolation est pertinente lorsque trois processus xcodebuild ou plus peuvent toucher la même famille de workspace sur une fenêtre glissante de 24 heures — typique du trunk iOS ou des usines white-label. Sans chemins dédiés, les pièces jointes XCTest disparaissent et l’indexation se bat avec la compilation. Regrouper les IO temporaires sous un arbre prévisible permet de décider d’ajouter un second M4 à partir des courbes disque, pas d’une impression.

Défaillances observées sur builders SSH headless

  • Indexer pendant le build — l’index du job A mute ce que le job B lit, d’où « type introuvable » jusqu’à un clean complet.
  • TMPDIR partagé — SwiftPM/clang laissent des centaines de milliers de petits fichiers ; le script de nettoyage d’un autre job supprime encore un préfixe ouvert.
  • xcresult sans quotas — vidéos et captures UI : trois suites peuvent dépasser 8 Go.
  • Archive puis tests — enchaîner sur le même DerivedData augmente le risque de corruption si l’archive s’arrête à mi-chemin.
Règle d’or : traitez DERIVED_DATA_PATH, TMPDIR, le chemin du bundle de résultats et -clonedSourcePackagesDirPath comme un unique préfixe de job créé à l’enqueue et supprimé via trap à la sortie.

Stratégies d’isolation comparées

Approche Avantages Inconvénients Quand
DERIVED_DATA_PATH par job sous /Volumes/builds Nettoyages déterministes, quotas par pipeline Premier build plus lent sans cache chaud CI parallèle sur Mac mini M4 partagé
Cache chaud lecture seule + copie overlay Compilations froides plus rapides rsync complexe ; difficile en SSH pur Trains de release avec mêmes mineurs Xcode
Comptes utilisateur macOS séparés Isolement fort des identités de signature Coût ops et licences plus élevés Locataires réglementés mélangés

Budget NVMe : chiffres copiables

Artefact Régime typique Pic UI tests
DerivedData (app moyenne, Debug) 6–14 Go + 3 Go scratch
Checkout SwiftPM + build 1–4 Go + 2 Go si nouveaux tags
Bundle xcresult 400–900 Mo tests unitaires 3–10 Go avec vidéo
Marge : gardez au moins 35 % de libre sur le volume du job ; en dessous de 50 Go libres, suspendez les nouveaux jobs et ne supprimez que des préfixes > 36 h non référencés par des PID actifs.

Runbook en huit étapes pour Mac cloud loués

  1. HorodaterJOB_ID=$(date +%s)-$RANDOM, ROOT=/Volumes/builds/$JOB_ID, mkdir -p pour DerivedData/tmp/results.
  2. Épingler l’environnement — exporter DERIVED_DATA_PATH, TMPDIR, TEMP, TMP.
  3. trap — après vérification d’unicité du JOB_ID, trap 'rm -rf "$ROOT"' EXIT ; agents long-running archivent d’abord.
  4. xcodebuild — ajouter -resultBundlePath "$ROOT/results/Test-$JOB_ID.xcresult" pour les tests ; IPA vers stockage objet selon export IPA.
  5. SwiftPM-clonedSourcePackagesDirPath "$ROOT/spm" aligné sur l’auth registre de l’article SwiftPM.
  6. Plafond de parallélisme — sur 24 Go RAM, limitez à ≤2 jobs UI lourds ; mutex côté file.
  7. Uploadditto -c -k --sequesterRsrc --keepParent puis contrôle d’intégrité avant suppression locale.
  8. Télémétriedf -h avant/après ; alerte si durée > 42 min avec disque > 90 % (pièces jointes en folie).

export JOB_ROOT=/Volumes/builds/ci-$CI_PIPELINE_ID mkdir -p "$JOB_ROOT"/{dd,tmp,res,spm} export DERIVED_DATA_PATH="$JOB_ROOT/dd" TMPDIR="$JOB_ROOT/tmp" TEMP="$JOB_ROOT/tmp" TMP="$JOB_ROOT/tmp"

Crochets métriques ajoutables en une demi-journée

Sans observation, l’isolation disque ne sert à rien. Émettez trois jauges : (1) du -sk "$ROOT" post-compile, (2) secondes murales dans xcodebuild archive, (3) gigaoctets libres sur le volume hébergeant /Volumes/builds. Si la taille médiane DerivedData dérive de plus de 18 % semaine sur semaine, cherchez d’abord une désactivation d’incremental ou une étape de codegen lourde, pas un achat matériel immédiat. Journalisez aussi le numéro de build Xcode avec JOB_ID : alterner 16.2 et 16.3 sur un même hôte fragmente l’index. Planifiez xcrun simctl delete unavailable hors fenêtres de pointe.

Pont vers SwiftPM et discipline de signature

L’isolation DerivedData ne remplace pas l’hygiène de provisioning. Les rotations hebdomadaires de certificats doivent suivre le guide signature automatique vs manuelle pour éviter que codesign n’attende une UI. Gardez Package.resolved versionné et évitez de mélanger un répertoire global SourcePackages avec un DerivedData par job — les verrouillages de checkout restent des courses.

FAQ : DerivedData sur Apple Silicon loué

Question Réponse pratique
Lier DerivedData vers NFS ? Évitez sauf RTT < 2 ms ; préférez NVMe local + upload d’artefacts.
Layout Xcode Server legacy ? Ignorez /Library/Developer/XcodeServer ; imposez des chemins explicites.
Rosetta ? Ne mélangez pas simulateurs x86_64 et préfixes arm64 ; isolez par architecture.

Pourquoi les nœuds régionaux M4 comptent encore

Les dossiers isolés suppriment les courses logicielles, pas la physique : tirer des artefacts depuis US Est depuis Tokyo coûte des minutes RTT. Colocalisez builders, SCM et auditeurs ; l’empreinte MacXCode HK / JP / KR / SG / US sert à placer /Volumes/builds sur le bon continent. Lisez l’aide pour les bases SSH, puis montez la concurrence seulement après 14 nuits consécutives de métriques disque au vert.

En bref : DERIVED_DATA_PATH + TMPDIR + chemins xcresult explicites transforment les builds rouges aléatoires en budgets IO mesurables — puis vous pouvez dimensionner via les tarifs plutôt qu’au doigt mouillé.

Montez en charge sur M4 bare metal isolé

HK · JP · KR · SG · US · SSH / VNC