0Pricing
Swift Academy · Leçon

Optimiser les chemins critiques : COW, inlining et spécialisation

Appliquer @inline, @_specialize et des optimisations des types valeur à partir des données du profileur.

Optimiser les chemins critiques : COW, inlining et spécialisation est une leçon Swift Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Swift Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Swift Academy comprend 4 leçons au total.

Identifier avant d’optimiser

Effectuez toujours un profilage en premier. N’optimisez que le code que Time Profiler identifie comme un chemin critique : l’optimisation prématurée fait perdre du temps.

// Measure → Identify → Optimise → Re-measure
// A 10ms function called once is less important than
// a 0.1ms function called 10,000 times per frame

Copie lors de l’écriture (COW)

Les types-valeurs de Swift (tableaux, dictionnaires) utilisent COW : le stockage est partagé jusqu’à une mutation, ce qui évite les copies inutiles.

var a = [1, 2, 3, 4, 5]
var b = a         // no copy yet, shared buffer
b.append(6)       // copy happens here (b mutates)
print(a.count)    // 5 — a unchanged

Garantir COW dans les types personnalisés

Implémentez COW dans les types-valeurs personnalisés en encapsulant l’état mutable dans un type référence et en le copiant avant toute mutation.

struct Matrix {
  private class Storage { var data: [[Double]] }
  private var storage = Storage()
  private mutating func ensureUnique() {
    if !isKnownUniquelyReferenced(&storage) {
      storage = Storage(data: storage.data)  // copy on write
    }
  }
  mutating func set(row: Int, col: Int, value: Double) {
    ensureUnique()
    storage.data[row][col] = value
  }
}

@inline(__always)

Forcez le compilateur à intégrer une fonction à chaque site d’appel, ce qui élimine le coût des appels pour les petites fonctions appelées dans des boucles serrées.

@inline(__always)
func clamp(_ value: Float, _ min: Float, _ max: Float) -> Float {
  return Swift.max(min, Swift.min(max, value))
}

@inline(never)

Empêchez l’intégration afin de réduire la taille du code ou de forcer le compilateur à considérer un chemin comme rarement utilisé.

@inline(never)
func handleUnexpectedError(_ error: Error) {
  // Large error-handling block — never inline to keep hot path small
}

@_specialize pour les types génériques

Demandez au compilateur d’émettre une copie spécialisée d’une fonction générique pour un type précis, ce qui permet une répartition statique et des optimisations SIMD.

@_specialize(where T == Float)
@_specialize(where T == Double)
func normalize<T: FloatingPoint>(_ values: [T]) -> [T] {
  let max = values.max()!
  return values.map { $0 / max }
}

Optimisation du module entier

WMO (activée dans Release) permet au compilateur d’intégrer et de spécialiser du code au-delà des limites des fichiers au sein d’un module.

// Xcode: Build Settings → Swift Compiler → Code Generation
// Optimization Level: Optimize for Speed (-O)
// Compilation Mode: Whole Module
// Enables cross-file inlining and dead code elimination

Éviter le coût d’ARC

La création fréquente de types référence dans les chemins critiques entraîne un coût de rétention et de libération lié à ARC. Préférez les types-valeurs ou mettez les références en cache.

// HOT PATH:
for _ in 0..<1_000_000 {
  let obj = HeavyClass()  // alloc + dealloc + ARC overhead
}
// BETTER: allocate once outside the loop
let obj = HeavyClass()
for _ in 0..<1_000_000 { obj.process() }

Utiliser ContiguousArray

ContiguousArray garantit un stockage contigu (contrairement à Array pour les éléments de classe), ce qui améliore les performances du cache dans les boucles serrées.

var nums = ContiguousArray<Float>(repeating: 0, count: 10_000)
// Faster iteration than Array<Float> for bridged-to-ObjC types

Réduire les recherches dans les tables de témoins de protocoles

La répartition dynamique des protocoles utilise des tables de témoins. Les types génériques et la spécialisation remplacent les recherches dans ces tables par des appels directs.

// Dynamic dispatch (slower for hot path):
func process(_ drawable: any Drawable) { drawable.draw() }
// Static dispatch after specialization:
func process<T: Drawable>(_ drawable: T) { drawable.draw() }
// Compiler may devirtualize and inline

Évaluer les performances avec XCTMeasure

Validez toujours les optimisations avec des tests de performance XCTMeasure dans votre suite de tests afin d’éviter les régressions.

func testNormalizePerformance() {
  let data = Array(0..<100_000).map { Float($0) }
  measure {
    _ = normalize(data)
  }
}

Vérification rapide

Que vérifie isKnownUniquelyReferenced(_:) lors de l’implémentation de la copie lors de l’écriture ?

Récapitulatif de la leçon

Commencez par effectuer un profilage avec Instruments. Appuyez-vous sur le COW intégré à Swift pour les collections ; implémentez-le dans les types-valeurs personnalisés avec isKnownUniquelyReferenced. Utilisez @inline(__always) pour les petites fonctions des chemins critiques, @_specialize pour les points chauds génériques, et activez WMO dans les versions Release. Validez chaque optimisation avec les tests de performance XCTMeasure.

Questions Fréquemment Posées

La leçon « Optimiser les chemins critiques : COW, inlining et spécialisation » est-elle gratuite ?

Oui — le texte complet de « Optimiser les chemins critiques : COW, inlining et spécialisation » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Swift Academy, passe à CoddyKit PRO. Le cours Swift Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Optimiser les chemins critiques : COW, inlining et spécialisation » ?

Appliquer @inline, @_specialize et des optimisations des types valeur à partir des données du profileur. Tu pratiques Swift Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Swift Academy ?

Aucune expérience préalable n'est requise. Swift Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Optimiser les chemins critiques : COW, inlining et spécialisation » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Swift Academy ?

Oui. Chaque leçon Swift Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Fondamentaux d’Instruments : Time Profiler
  2. Instruments Allocations et Leaks
  3. Main Thread Checker et blocages
  4. Optimiser les chemins critiques : COW, inlining et spécialisation
← Retour à Swift Academy