Swift Beta Performance : Tri des tableaux — qu'est-ce qui a mal tourné ?
\n\nSi vous avez déjà jeté un œil sur Stack Overflow à l'époque des premières versions bêta de Swift, vous vous souvenez sûrement de la question légendaire qui a rassemblé des milliers de vues et des centaines de commentaires. Elle ressemblait à ceci : « Pourquoi le tri des tableaux en Swift Beta est-il 100 fois plus lent qu'en Objective-C ? »
\n\nÀ l'époque, en 2014, ce fut un véritable choc pour la communauté iOS. Les développeurs, habitués au tri fulgurant en Objective-C, ont soudain vu leurs applications se bloquer sans raison apparente. Aujourd'hui, des années plus tard, nous pouvons analyser ce problème sereinement : comprendre ce qui causait les ralentissements, comment Swift a évolué et, surtout, comment trier correctement les tableaux en Swift moderne pour ne pas répéter les erreurs du passé.
\n\nDans cet article, nous ne nous contenterons pas de raconter un ancien bug. Nous réaliserons nos propres tests, écrirons du code et découvrirons quels algorithmes de tri en Swift sont vraiment rapides, et lesquels sont un piège pour les débutants. C'est parti !
\n\nPetit historique : que s'est-il passé dans Swift Beta ?
\n\nDans la première version bêta de Swift, le tri d'un tableau de 100 000 entiers pouvait prendre jusqu'à 20 secondes. En Objective-C, la même opération s'effectuait en 0,2 seconde. Une différence de 100 fois ! La raison résidait dans le fait que le premier Swift utilisait une implémentation inefficace de l'algorithme de tri (Introsort avec un mauvais choix de pivot), et avait également des problèmes d'optimisation lors de la compilation sans indicateurs d'optimisation (-O).
\n\nDe plus, dans la version bêta, le mécanisme de vérification dynamique des limites (bounds checking) se déclenchait souvent pour chaque accès au tableau, ajoutant des frais généraux énormes. La conclusion était simple : Swift était brut, mais son potentiel était énorme.
\n\nComment trier les tableaux en Swift aujourd'hui ? Bonnes pratiques
\n\nLe Swift moderne (versions 5.x et plus récentes) est un langage mature. Le tri des tableaux est devenu non seulement rapide, mais l'un des plus rapides parmi les langages courants. Passons en revue les méthodes principales.
\n\n1. La méthode intégrée sort() — l'étalon-or
\n\nLa manière la plus simple et recommandée est d'utiliser la méthode sort() (tri sur place) ou sorted() (retourne un nouveau tableau trié).
import Foundation\n\nvar numbers = [5, 3, 8, 1, 9, 2]\nnumbers.sort() // tri sur place\nprint(numbers) // [1, 2, 3, 5, 8, 9]\n\nlet sortedNumbers = numbers.sorted() // retourne un nouveau tableau\nprint(sortedNumbers) // [1, 2, 3, 5, 8, 9]\n\nEn interne, sort() utilise TimSort — un algorithme hybride qui fonctionne en O(n log n) en moyenne et O(n) sur des données presque triées. C'est le même algorithme utilisé en Python et Java. Il est parfaitement optimisé pour les processeurs modernes.
2. Tri avec fermeture : personnalisation
\n\nSi vous devez trier un tableau par ordre décroissant ou selon un critère complexe, utilisez une fermeture :
\n\nlet words = ["pomme", "orange", "banane", "kiwi"]\nlet sortedByLength = words.sorted { $0.count < $1.count }\nprint(sortedByLength) // ["kiwi", "pomme", "banane", "orange"]\n\nlet descendingNumbers = numbers.sorted(by: >)\nprint(descendingNumbers) // [9, 8, 5, 3, 2, 1]\n\nImportant : la fermeture doit être une fonction pure (pure function) — sans effets secondaires. Sinon, vous risquez un comportement imprévisible et une baisse de performance.
\n\n3. Tri de structures personnalisées
\n\nLorsque vous travaillez avec vos propres types de données, il est préférable d'implémenter le protocole Comparable. Cela permettra d'utiliser sort() sans fermeture.
struct Person: Comparable {\n let name: String\n let age: Int\n\n static func < (lhs: Person, rhs: Person) -> Bool {\n return lhs.age < rhs.age // tri par âge\n }\n}\n\nle