Performance 15. April 2026

2026-04-15 Xcode DerivedData, TMPDIR & xcresult-Isolation auf gemietetem Cloud-Mac-CI

MacXCode Engineering-Team 15. April 2026 ~13 Min.

Mobile Release-Teams, die Mac mini M4-Builder in Hongkong, Tokio, Seoul, Singapur und US East mieten, geben oft „langsames Xcode“ an, während die Ursache Dateisystemkonkurrenz ist: zwei Pipelines schreiben dieselbe DerivedData-Partition, ein UI-Testjob füllt /tmp, oder ein .xcresult-Bundle wächst über 6 GB und verhungert parallele Archive. Dieses Playbook vom 2026-04-15 erklärt, wer Job-Isolation braucht, katalogisiert reale Ausfälle auf headless-SSH-Hosts, vergleicht Strategien tabellarisch, liefert ein numeriertes Acht-Schritte-Shell-Runbook und verlinkt SwiftPM-Registry & Cache sowie automatische vs. manuelle Signierung, damit Folgeschritte deterministisch bleiben.

Apple Silicon auf Bare Metal reduziert CPU-Rauschen, aber NVMe-Schreibdurchsatz bleibt endlich. Das Teilen von ~/Library/Developer/Xcode/DerivedData erzeugt stochastische SwiftEmitModule-Fehler. Binden Sie DERIVED_DATA_PATH, TMPDIR, -resultBundlePath und -clonedSourcePackagesDirPath an ein gemeinsames Job-Präfix, dann wird Kapazitätsplanung messbar statt bauchgefühlt — auch beim Vergleich regionaler Knoten.

Wer profitiert von Job-DerivedData auf Cloud-Macs

Isolation zahlt sich aus, wenn innerhalb eines rollierenden 24-Stunden-Fensters drei oder mehr gleichzeitige xcodebuild-Prozesse dieselbe Workspace-Familie berühren können — typisch für trunk-basierte iOS-Shops oder White-Label-Fabriken. Ohne eigene Pfade bleiben Modulkarten und XCTest-Anhänge fragil. Vorhersagbare Bäume pro Job machen die Frage „zweites M4?“ datengetrieben.

Fehlermuster auf headless-SSH-Buildern

  • Index während Build — Hintergrundindexierung aus Job A mutiert Indizes, die Job B mittendrin liest („Typ nicht gefunden“ bis Clean).
  • Gemeinsames TMPDIR — SwiftPM/clang erzeugen massenhaft kleine Dateien; ein Cleanup eines anderen Jobs löscht noch referenzierte Präfixe.
  • xcresult ohne Quoten — UI-Tests mit Video + Screenshots: drei Suites > 8 GB.
  • Archiv + Tests verzahnt — Nachtjobs archivieren und testen auf demselben DerivedData-Pfad; abgebrochene Archive erhöhen Korruptionsrisiko.
Goldene Regel: Behandeln Sie DERIVED_DATA_PATH, TMPDIR, Ergebnispfad und -clonedSourcePackagesDirPath als ein Job-Präfix, das bei Queue-Zeit entsteht und per trap endet.

Isolationsstrategien im Vergleich

Ansatz Pro Contra Wann
Per-job DERIVED_DATA_PATH unter /Volumes/builds Deterministische Cleans, Quoten pro Pipeline Erster Build ohne Warmcache langsamer Parallele CI auf geteiltem Mac mini M4
Read-only Warmcache + Overlay-Kopie Schnellere Kaltkompilate Komplexes rsync, schwierig rein SSH Release-Züge mit identischen Xcode-Minoren
Separate macOS-Benutzerkonten Harte Isolation von Signing-Identitäten Höhere Ops-Kosten und Lizenzen Regulierte Mandanten mit gemischten Apps

NVMe-Budget: Zahlen fürs Runbook

Artefakt Typischer Dauerzustand Spitze UI-Tests
DerivedData (mittlere App, Debug) 6–14 GB + 3 GB Scratch
SwiftPM Checkout + Build 1–4 GB + 2 GB bei neuen Tags
xcresult-Bundle 400–900 MB Unit-Tests 3–10 GB mit Video
Kopfroom: Mindestens 35 % frei auf dem Job-Volume; unter 50 GB frei neue Jobs pausieren und nur Präfixe älter als 36 Stunden ohne laufende PID löschen.

Acht-Schritte-Runbook für gemietete Cloud-Macs

  1. Job stempelnJOB_ID=$(date +%s)-$RANDOM, ROOT=/Volumes/builds/$JOB_ID, Unterordner anlegen.
  2. Umgebung pinnenDERIVED_DATA_PATH, TMPDIR, TEMP, TMP setzen.
  3. trap — nach Kollisionscheck trap 'rm -rf "$ROOT"' EXIT; Langläufer zuerst Artefakte archivieren.
  4. xcodebuild — Tests mit -resultBundlePath "$ROOT/results/Test-$JOB_ID.xcresult"; IPA laut IPA-Export in Objektspeicher.
  5. SwiftPM-clonedSourcePackagesDirPath "$ROOT/spm" plus Registry-Auth wie im SwiftPM-Artikel.
  6. Parallelitätsdeckel — bei 24 GB RAM schwere UI-Tests auf ≤2; Mutex in der Queue.
  7. Uploadditto -c -k --sequesterRsrc --keepParent, Checksumme, dann lokales zip löschen.
  8. Telemetriedf -h vor/nach; Alarm bei Wandzeit > 42 Min und > 90 % Platte (Anhänge).

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"

Metrik-Hooks für einen Nachmittag

Ohne Messung ist Verzeichnis-Isolation wirkungslos. Drei Gauges: (1) du -sk "$ROOT" nach Compile, (2) Wandzeit xcodebuild archive, (3) freie GB auf dem Volume mit /Volumes/builds. Wenn die mediane DerivedData-Größe wöchentlich > 18 % steigt, prüfen Sie inkrementelles Deaktivieren oder Codegen — nicht sofort Hardware. Loggen Sie xcodebuild -version neben JOB_ID, um Wechsel zwischen 16.2 und 16.3 mit Spike zu korrelieren. xcrun simctl delete unavailable außerhalb von Peak-Fenstern planen.

Brücke zu SwiftPM & Signing-Disziplin

DerivedData-Isolation ersetzt keine Provisioning-Hygiene. Wöchentliche Zertifikatsrotation braucht Auto- vs. Manual-Signing, damit codesign nicht auf UI wartet. Halten Sie Package.resolved versioniert und mischen Sie kein globales SourcePackages mit per-job DerivedData — Checkout-Sperren bleiben Wettläufe.

FAQ: DerivedData auf gemietetem Apple Silicon

Frage Praktische Antwort
DerivedData per Symlink auf NFS? Vermeiden, außer RTT < 2 ms; lieber lokales NVMe + Artefakt-Upload.
Xcode Server Legacy? Moderne CI ignoriert /Library/Developer/XcodeServer; immer explizite Pfade setzen.
Rosetta-Mix? x86_64-Simulatoren nicht mit arm64-Präfixen mischen; architekturgetrennt isolieren.

Warum regionale Mac-mini-M4-Knoten weiter zählen

Verzeichnis-Isolation beseitigt Software-Races, nicht die Physik: Ingenieure in Tokio, die Artefakte aus US East ziehen, zahlen RTT in Minuten. Colokalisieren Sie Builder nahe SCM und Tester; das MacXCode-Fußabdruck HK / JP / KR / SG / US hält /Volumes/builds auf dem Kontinent Ihrer Git-LFS- und Audit-Logs. Lesen Sie Hilfe zu SSH-Baselines, skalieren Sie erst nach 14 grünen Nächten Disk-Telemetrie.

Fazit: Per-job DERIVED_DATA_PATH + TMPDIR + explizite xcresult-Pfade machen „zufällige rote Builds“ zu messbaren IO-Budgets — dann tragen Preise statt Bauchgefühl.

Isolierte Builder auf Bare-Metal-M4 skalieren

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