Introduction : pourquoi le profilage du code Swift est une nécessité
Le développement iOS et macOS exige des performances élevées. Même une seule méthode lente peut provoquer des ralentissements dans l'UI, une décharge de la batterie ou un blocage de l'application. Le profilage du code Swift est le processus d'analyse du temps d'exécution, de la mémoire et de l'utilisation du CPU, qui permet de trouver et de résoudre les goulots d'étranglement. Sans profilage, l'optimisation devient un jeu de devinettes : vous modifiez le code au hasard, sans savoir ce qui ralentit réellement.
Dans cet article, nous allons passer en revue les principaux outils de profilage Swift : Xcode Instruments, os_signpost et la mesure manuelle du temps. Vous apprendrez à trouver les fonctions lentes, les fuites mémoire et les algorithmes inefficaces. Cet article sera utile aussi bien aux débutants qu'aux développeurs iOS expérimentés.
Outil n°1 : Xcode Instruments – votre principal assistant
Xcode Instruments est un ensemble puissant de profileurs intégré à Xcode. L'outil le plus populaire est le Time Profiler. Il montre combien de temps le CPU consacre à chaque fonction. Il se lance via le menu Product > Profile ou le raccourci Cmd + I.
Comment utiliser Time Profiler
- Lancez le profilage de votre application.
- Effectuez l'action qui semble lente (défilement, chargement de données, animation).
- Arrêtez l'enregistrement et examinez la pile d'appels.
- Trouvez les fonctions avec le plus grand temps d'exécution (colonnes rouges).
Exemple : si votre tableView(_:cellForRowAt:) occupe 80% du temps, le problème vient de là. Un double-clic affichera les lignes de code spécifiques.
Exemple de code pour le profilage
Supposons que vous ayez une fonction de chargement d'images :
func loadImage(from url: URL) -> UIImage? { guard let data = try? Data(contentsOf: url) else { return nil } return UIImage(data: data)}Le Time Profiler montrera que Data(contentsOf:) bloque le thread principal. La solution est un chargement asynchrone via URLSession.
Outil n°2 : os_signpost – profilage ciblé
Parfois, il est nécessaire de mesurer uniquement une partie du code sans encombrer le profil général. Pour cela, utilisez os_signpost – une API légère pour marquer des événements. Les données sont automatiquement intégrées dans Instruments.
Configuration de os_signpost
Importez d'abord os et créez un logger :
import os
let log = OSLog(subsystem: "com.yourapp.network", category: "Loading")Ensuite, encadrez le code à mesurer :
os_signpost(.begin, log: log, name: "FetchData")// Votre code de chargementos_signpost(.end, log: log, name: "FetchData")Dans Instruments, sélectionnez le modèle os_signpost – vous verrez le temps d'exécution exact de chaque bloc. C'est indispensable pour comparer deux algorithmes.
Exemple concret : comparaison de tris
Comparons le tri standard et le tri manuel :
os_signpost(.begin, log: log, name: "SortBuiltin")let sortedBuiltin = largeArray.sorted()os_signpost(.end, log: log, name: "SortBuiltin")
os_signpost(.begin, log: log, name: "SortManual")let sortedManual = largeArray.sorted { $0 < $1 }os_signpost(.end, log: log, name: "SortManual")Le résultat surprend souvent : le tri intégré est 30 à 40% plus rapide que le tri manuel.
Outil n°3 : Mesure manuelle du temps avec DispatchTime
Pour des vérifications rapides sans Instruments, utilisez DispatchTime. C'est une méthode simple pour mesurer le temps d'exécution d'une fonction directement dans le code.
Exemple de mesure
let start = DispatchTime.now()// Bloc à mesurerlet result = heavyComputation()let end = DispatchTime.now()
let nanoTime = end.uptimeNanoseconds - start.uptimeNanosecondslet timeInterval = Double(nanoTime) / 1_000_000_000print("Temps d'exécution : \\(timeInterval) s")