Traquer les fuites mémoire avec Instruments sur un Mac mini cloud distant
Deux heures du matin, un testeur envoie le scénario juste avant le crash : après une quinzaine d'allers-retours sur un même écran, la consommation mémoire grimpe de 80 Mo à 600 Mo avant que le système ne tue l'application. Ce genre de fuite « à croissance lente » est quasiment impossible à repérer à l'œil nu dans le code ; il faut obligatoirement passer par Instruments. Le problème, c'est que le Mac local de l'équipe est en permanence saturé par les simulateurs et les builds : lancer en plus une session d'échantillonnage Instruments fait décoller les ventilateurs, et les données restent bruitées. On a fini par déplacer tout ce processus de diagnostic sur un Mac mini cloud : une machine physique dédiée, sans voisin pour se disputer les ressources, avec un bruit d'échantillonnage nettement plus faible. Voici comment on procède concrètement.
Pourquoi diagnostiquer sur une machine physique dédiée
Instruments a lui-même un coût CPU et mémoire non négligeable : le template Leaks effectue périodiquement un balayage du tas, Allocations enregistre la pile d'appel de chaque allocation. Si l'hôte est un environnement partagé, découpé en tranches de temps entre plusieurs tâches, la timeline d'échantillonnage se remplit de perturbations d'ordonnancement sans rapport, la courbe devient sale et on risque de mal interpréter les « points de croissance ». L'avantage d'une machine physique dédiée est très simple : quasiment chaque saut de mémoire observé correspond réellement à une action de votre propre code, sans avoir à d'abord se demander « est-ce qu'une autre tâche est en train de me piquer des ressources ? ».
Le pire, quand on traque un problème mémoire, n'est pas de ne pas trouver d'indice, mais d'en trouver un tas de faux — plus l'environnement est bruité, plus les faux indices s'accumulent.
Préparation : partage d'écran + alignement des versions
Une fois le Mac mini cloud démarré, connectez-vous d'abord via le partage d'écran natif (VNC), en réglant la résolution à au moins 1920x1080 : la timeline d'Instruments devient illisible en basse résolution, les détails se superposent.
# Terminal local, on vérifie d'abord la disponibilité via SSH
ssh dev@<adresse-de-votre-instance> "sw_vers -productVersion; xcodebuild -version"
# Connexion via un client VNC, à l'adresse attribuée à l'instance (interne/publique)
open "vnc://dev@<adresse-de-votre-instance>"
Une fois connecté, la première chose à faire est de vérifier que la version de Xcode correspond bien à celle de votre machine de développement locale : un écart de version dans la bibliothèque de templates d'Instruments peut faire disparaître certaines fonctionnalités récentes (par exemple le traçage lié à Swift Concurrency). Vérifiez le bon chemin des outils en ligne de commande avec xcode-select -p, puis ouvrez Xcode → Open Developer Tool → Instruments.
Localiser la fuite avec le template Leaks
Créez un nouveau Profile, choisissez l'appareil (soit un appareil réel connecté au Mac mini cloud, soit un simulateur pour reproduire le bug), et sélectionnez le template Leaks. Leaks balaie périodiquement le tas en arrière-plan ; les objets marqués en rouge sont des objets orphelins toujours présents alors que leur compteur de références est retombé à zéro.
Étapes :
- Lancez l'enregistrement, puis déclenchez l'action suspecte dans l'app (par exemple entrer/sortir d'un écran) 15 à 20 fois de suite ;
- Observez la piste Leaks à gauche : repérez à quel moment (donc quelle action) chaque marqueur rouge apparaît ;
- Ouvrez l'entrée Leak correspondante ; le panneau Extended Detail à droite affiche la pile d'appel d'allocation, permettant de sauter directement à la classe et à la méthode concernées.
La limite de Leaks est qu'il ne signale que des « fuites certaines ». Des cas comme une référence forte via NSTimer ou une closure capturant self — où la chaîne de références n'est pas rompue mais où l'objet devrait logiquement être libéré — passent souvent sous le radar. Il faut alors basculer sur Allocations.
Lire la courbe de croissance avec Allocations
Créez un nouveau Profile avec le template Allocations, et cochez Record Reference Counts. Répétez la même séquence d'actions, en cliquant manuellement sur Mark Generation à la fin de chaque itération : cela place un repère sur la timeline, ce qui permet de comparer facilement « après chaque cycle, la mémoire est-elle bien redescendue à son point de départ ? ».
Lecture clé : si la courbe mémoire monte en escalier sur plusieurs cycles, avec des marches de hauteur à peu près identique, on peut quasi certainement conclure qu'un objet ou un tableau fixe s'accumule à chaque opération. Basculez sur la vue « All Heap Allocations », triez par Growth, et comparez avec les Generation marquées : vous voyez directement quelle classe voit son nombre d'instances augmenter de façon stable.
| Critère d'observation | Leaks | Allocations |
|---|---|---|
| Détecte les cycles de référence closure/Timer | Faible | Fort |
| Efficacité de localisation | Rapide, marquage rouge direct | Nécessite plusieurs comparaisons |
| Phase d'usage recommandée | Filtrage initial | Localisation précise de la source de croissance |
Confirmer avec Memory Graph
Une fois la classe suspecte identifiée dans Instruments, retournez dans Xcode et lancez Debug Memory Graph (l'icône mémoire de la barre de debug), en déclenchant la même séquence d'actions. Memory Graph dessine le graphe des relations de référence entre objets : les points d'exclamation violets signalent les cycles de référence potentiels. Cette étape confirme une seconde fois la conclusion d'Instruments, et permet surtout de voir clairement « qui référence fortement qui », de manière bien plus visuelle que la pile d'appel d'Instruments pour localiser précisément une ligne du type self.completion = { self.doSomething() }, typique d'une capture de closure problématique.
Une fois le correctif appliqué, ne concluez pas trop vite : relancez la même séquence d'actions sous Allocations et vérifiez que la courbe entre les Mark Generation est bien horizontale, et non plus en escalier. C'est seulement à ce moment que la correction est réellement validée.
Pièges fréquents et liste de vérification
- Effectuez toujours une action de « préchauffage » avant l'enregistrement (démarrage, connexion, etc., allocations ponctuelles), pour éviter de confondre les allocations normales du démarrage à froid avec une fuite ;
- Le comportement mémoire diffère entre les configurations Debug et Release ; toute conclusion finale doit être revérifiée en configuration Release ;
- Sur un Mac mini cloud, une déconnexion/reconnexion du partage d'écran peut interrompre la session Instruments ; avant un enregistrement long, utilisez
caffeinate -ipour empêcher le système de se mettre en veille pendant l'échantillonnage ; - Après chaque correctif, revalidez systématiquement avec la méthode de comparaison des Generation dans Allocations, plutôt que de conclure sur la seule base d'une relecture de code.
Questions fréquentes
Un Mac mini cloud est-il assez rapide pour Instruments ?
Oui. Instruments ajoute lui-même de la charge CPU et mémoire; une machine physique dédiée sans voisins donne des échantillons plus propres, essentiel pour lire des timelines fines.
Une résolution de partage d'écran faible gêne-t-elle le travail ?
Elle réduit la lisibilité de la timeline. Réglez le VNC sur au moins 1920x1080 et zoomez sur la plage temporelle visée avant de capturer les preuves.
Faut-il arrêter la location dès la fuite trouvée ?
Pas encore. Appliquez d'abord le correctif sur la même instance et vérifiez que la courbe d'allocation se stabilise avant de décider de clore la période en cours.
portal://order
Besoin d'une machine dès maintenant ?
Mac mini physique dédié, location à la journée dès le départ, disponible en environ 4 minutes après le paiement.