Lorsqu’un même commit est compilé plusieurs fois de suite sur un Mac dans le cloud, un premier build de 11 minutes puis un quatrième de 15 minutes ne suffisent pas pour conclure à une « instabilité des performances de la machine ». Les résultats peuvent suivre une courbe similaire en raison du cache, des processus d’indexation, de l’exécution parallèle des tests ou de la pression thermique. La bonne méthode consiste à figer les variables, à enchaîner les mesures, puis à vérifier si l’augmentation du temps de build coïncide avec celle de la consommation électrique et de la pression thermique.
Définir d’abord un échantillon de build reproductible
Le diagnostic doit porter sur une commande reproductible de manière fiable, et non sur un Scheme lancé ponctuellement par un développeur. Figez le commit, le chemin de Xcode, le SDK, la cible, la configuration de build et le répertoire DerivedData, puis consignez le temps d’inactivité écoulé depuis le démarrage de la machine. Si vous changez de branche ou mettez à jour les dépendances à chaque exécution, vous ne mesurez que les variations de la charge de travail.
Sur les nœuds physiques dédiés de VMOrbit, les ressources de l’hôte ne sont pas perturbées par l’ordonnancement des machines virtuelles d’autres locataires. Des conflits peuvent néanmoins survenir au sein du nœud entre l’indexation, la résolution des dépendances, les simulateurs et des processus de build résiduels. Commencez par enregistrer les informations de base sur l’environnement :
mkdir -p "$HOME/build-thermal-check"
system_profiler SPHardwareDataType > "$HOME/build-thermal-check/hardware.txt"
xcodebuild -version > "$HOME/build-thermal-check/xcode.txt"
pmset -g > "$HOME/build-thermal-check/power.txt"
ps -axo pid,%cpu,%mem,etime,command > "$HOME/build-thermal-check/processes-before.txt"
Mesurer séparément les builds à froid et à chaud
Les builds à froid servent à observer la charge d’une compilation complète, tandis que les builds à chaud permettent d’étudier le chemin incrémental. Ils ne doivent pas être mélangés dans un même ensemble statistique. Pour un build à froid, utilisez un nouveau répertoire DerivedData dédié. Pour un build à chaud, réutilisez le répertoire de l’exécution précédente. Ne videz pas les caches globaux, car cela pourrait affecter d’autres tâches exécutées sur le nœud.
| Échantillon | DerivedData | Objectif principal |
|---|---|---|
| Build à froid | Recréé pour chaque série | Comparer la charge soutenue d’une compilation complète |
| Build à chaud | Réutilisé au sein de la même série | Vérifier le build incrémental et l’efficacité du cache |
| Témoin au repos | Aucun build exécuté | Identifier les processus d’arrière-plan et la consommation de référence |
Mesurer simultanément la durée et la pression thermique
Le temps total ne suffit pas à démontrer un bridage thermique. Exécutez au moins trois builds consécutifs et collectez simultanément les données de powermetrics pendant chaque build. Cet outil nécessite généralement des privilèges d’administrateur ; l’autorisation doit être limitée à une commande et à des paramètres clairement définis.
RUN_ROOT="$HOME/build-thermal-check/run-01"
mkdir -p "$RUN_ROOT/DerivedData"
sudo powermetrics --samplers cpu_power -i 1000 -n 900 \
-o "$RUN_ROOT/powermetrics.txt" &
METRIC_PID=$!
/usr/bin/time -lp xcodebuild \
-workspace App.xcworkspace \
-scheme App \
-configuration Release \
-destination 'generic/platform=iOS' \
-derivedDataPath "$RUN_ROOT/DerivedData" \
build > "$RUN_ROOT/build.log" 2> "$RUN_ROOT/time.txt"
wait "$METRIC_PID"
pmset -g therm > "$RUN_ROOT/thermal.txt"
-n 900 limite la collecte à 900 échantillons. Si le build se termine plus tôt, l’échantillonnage en arrière-plan se poursuit. Le script du projet peut envoyer le signal TERM au processus d’échantillonnage à la fin du build, mais il doit conserver une gestion correcte de l’arrêt afin de ne pas laisser de processus actif dans la CI. Si powermetrics n’est pas disponible, enregistrez au minimum pmset -g therm, time -lp et un instantané des processus triés par utilisation du CPU.
Le bridage thermique est une conclusion étayée conjointement par la tendance des durées et les signaux système. Une seule observation d’une forte utilisation du CPU ne suffit pas à le confirmer.
Tirer des conclusions à partir de la courbe, pas d’un point isolé
Regroupez dans un même tableau la durée réelle de chaque exécution, la mémoire résidente maximale, la pression thermique et les processus fortement sollicités au même moment. Si la première exécution est lente et que les suivantes accélèrent nettement, il s’agit généralement du préchauffage du cache. Si une seule exécution ralentit soudainement en même temps qu’un téléchargement de dépendances ou qu’un processus d’indexation apparaît, la cause la plus probable est un conflit de ressources.
Le schéma le plus significatif est le suivant : alors que le code et l’état du cache restent inchangés, la durée augmente progressivement sur plusieurs exécutions consécutives ; le CPU demeure longtemps à pleine charge ; les signaux de pression thermique augmentent en parallèle ; après l’arrêt de la charge et une période de repos, l’exécution suivante revient à la normale. Le bridage thermique ne doit être considéré comme cause principale que lorsque tous ces indices sont réunis.
Écarter trois faux positifs courants
Vérifiez d’abord que le build ne lance pas discrètement des tests, un archivage ou un script de téléchargement. Comparez ensuite le nombre de fichiers compilés dans les journaux afin de confirmer que la charge de travail est identique à chaque exécution. Enfin, recherchez plusieurs processus xcodebuild, simulateurs ou gestionnaires de paquets fonctionnant en parallèle. Lors d’une exécution anormale, vous pouvez enregistrer :
date -u
pgrep -alf 'xcodebuild|swift-frontend|clang|Simulator'
top -l 3 -o cpu -stats pid,command,cpu,mem,time
du -sh "$RUN_ROOT/DerivedData"
Le classement instantané produit par top indique uniquement quels processus consommaient des ressources au moment de l’échantillonnage ; il ne permet pas, à lui seul, d’établir la cause racine. Le nombre de tâches et leur durée dans le journal de build sont les éléments qui relient l’état du système à la charge du projet.
Identifier le facteur déclencheur par des expériences contrôlées
Une fois la tendance confirmée, ne modifiez qu’une seule variable à la fois. Commencez par ramener à 1 le nombre de jobs CI simultanés tout en maintenant les autres conditions inchangées. Rétablissez ensuite le parallélisme, mais décalez les heures de démarrage. Comparez enfin les builds à froid et à chaud. Si la courbe des durées se stabilise lorsque le parallélisme diminue, le problème vient plus probablement d’une concurrence entre les tâches du même nœud ou d’une consommation soutenue trop élevée que d’une dégradation du compilateur lui-même.
N’utilisez pas un nettoyage plus agressif du cache comme solution immédiate. Cette opération augmente la charge de travail de l’exécution suivante et masque la tendance initiale. De même, un redémarrage ne constitue pas une preuve suffisante : il arrête simultanément les processus d’arrière-plan, réinitialise une partie de l’état du système et laisse à la machine le temps de refroidir. Il est donc impossible de savoir quel changement a réellement produit l’amélioration.
Ajuster l’ordonnancement des builds plutôt que poursuivre la fréquence instantanée
Une solution stable consiste généralement à limiter le nombre de tâches lourdes exécutées sur un même nœud, à décaler l’archivage, les suites de tests complètes et l’analyse statique, puis à attribuer un répertoire DerivedData distinct à chaque pipeline. Pour les tâches qui doivent impérativement s’exécuter en parallèle, mesurez d’abord la durée médiane avec une concurrence de 1, 2 et 3, puis retenez le niveau offrant le débit global le plus élevé plutôt que les meilleures performances maximales pour une tâche isolée.
Transformer le diagnostic en référence CI
La référence doit inclure la commande, le commit, la version de Xcode, le type de build, le nombre d’exécutions consécutives et leur durée médiane. N’utilisez pas l’exécution la plus rapide comme référence et ne bloquez pas une fusion à cause d’un seul dépassement de délai. Une règle plus robuste consiste à comparer de manière glissante les médianes des dernières exécutions, puis à générer un dossier de diagnostic seulement après plusieurs dépassements consécutifs du seuil.
Les artefacts finaux doivent au minimum comprendre le journal de build, la sortie de time, les relevés de pression thermique, les instantanés des processus et les paramètres d’échantillonnage. Si le problème doit être remonté, joignez la région du nœud, l’heure de l’incident, les étapes de reproduction et le minimum de journaux nécessaires, sans transmettre de mot de passe, de clé privée ni d’identifiants d’accès complets. Ainsi, lorsqu’une variation similaire réapparaîtra, l’équipe pourra relancer directement le même échantillon au lieu de recommencer le diagnostic à partir d’hypothèses.
Questions fréquentes
Un seul build Xcode lent suffit-il à conclure à un bridage thermique ?
Non. Il faut fixer le code, la version de Xcode, l’état du cache et le parallélisme, puis comparer au moins trois exécutions avec la puissance CPU, la pression thermique et les processus actifs.
powermetrics nécessite-t-il des droits administrateur ?
Généralement oui. Il est préférable d’autoriser uniquement une commande sudo aux paramètres limités et d’écrire les résultats dans un répertoire contrôlé.
Déployez vos tâches de build sur un Mac dédié dans le cloud
Choisissez VMOrbit M4 ou VMOrbit M4 Pro, puis sélectionnez un nœud en fonction de l’emplacement de votre équipe. La disponibilité et les informations de livraison affichées dans la console font foi en temps réel.