Comment Swift peut-il être tellement plus rapide que Objective-C dans ces comparaisons?

115

Apple a lancé son nouveau langage de programmation Swift à la WWDC14 . Dans la présentation, ils ont effectué des comparaisons de performances entre Objective-C et Python. Ce qui suit est une image d'une de leurs diapositives, d'une comparaison de ces trois langages réalisant un type d'objet complexe:

entrez la description de l'image ici

Il y avait un graphique encore plus incroyable sur une comparaison de performance utilisant l' algorithme de chiffrement RC4 .

De toute évidence, il s’agit d’un discours marketing, et ils n’ont pas expliqué en détail la façon dont cela a été mis en œuvre dans chacun d’eux. Je me demande cependant:

  1. Comment un nouveau langage de programmation peut-il être tellement plus rapide?
  2. Les résultats d'Objective-C sont-ils causés par un mauvais compilateur ou existe-t-il quelque chose de moins efficace dans Objective-C que Swift?
  3. Comment expliqueriez-vous une augmentation de performance de 40%? Je comprends que le contrôle de référence automatisé / récupération de place peut générer des coûts supplémentaires, mais c’est tout?
Jaune
la source
13
@MathewFoscarini Obj-C va à l'assembleur, mais il dispose d'un mécanisme d'envoi de messages d'objet coûteux. Pour la plupart des travaux d'interface graphique, cela n'a pas d'importance, mais pour le trier, cela compte beaucoup.
Donal Fellows
17
La comparaison avec Python est le vrai casse-tête ici.
asthasr
9
@syrion marketing, et le langage semble emprunter la syntaxe de python (un peu comme le golang). Ils essaient de dire « hey, les développeurs de Python, vous pouvez écrire quelque chose pas trop étrangère sur le Mac et l' ont soit beaucoup plus vite, encore plus vite que Objective C que vous ne fut jamais vraiment le coup de »
4
@MichaelT Je comprends ça, mais c'est quand même étrange. Quiconque connaît quelque chose sur les langages réalisera que Python, en tant que langage interprété, ne sera tout simplement pas dans la même situation qu'Objective-C ou d'autres langages compilés (pour la plupart des tâches). Son utilisation comme point de repère est étrange.
asthasr
7
Ils parlent probablement du temps nécessaire pour écrire le code ...
Lukas Eder

Réponses:

62

Premièrement, (IMO) comparer avec Python n'a presque pas de sens. Seule la comparaison avec Objective-C est significative.

  • Comment un nouveau langage de programmation peut-il être tellement plus rapide?

Objective-C est un langage lent. (Seule la partie C est rapide, mais c'est parce que c'est C) Cela n'a jamais été extrêmement rapide. C'était juste assez rapide pour leur objectif (Apple), et plus rapide que leurs anciennes versions. Et c'était lent parce que ...

  • Objective-C résulte-t-il d'un mauvais compilateur ou existe-t-il quelque chose de moins efficace dans Objective-C que Swift?

Objective-C garantissait la distribution dynamique de chaque méthode. Pas d'envoi statique du tout. Cela a rendu impossible l'optimisation d'un programme Objective-C. Eh bien, peut-être que la technologie JIT peut être utile, mais AFAIK, Apple déteste vraiment les caractéristiques de performances imprévisibles et la durée de vie des objets. Je ne pense pas qu'ils avaient adopté des trucs JIT. Swift ne dispose pas d’une telle garantie d’expédition dynamique, à moins que vous ne mettiez un attribut spécial pour la compatibilité Objective-C.

  • Comment expliqueriez-vous une augmentation de performance de 40%? Je comprends que le contrôle de référence automatisé / récupération de place peut générer des coûts supplémentaires, mais c’est tout?

GC ou RC n'a pas d'importance ici. Swift emploie également principalement RC. Il n'y a pas de GC, et ne le fera pas à moins d'un saut architectural énorme en matière de technologie GC. (IMO, c'est pour toujours) Je pense que Swift a beaucoup plus de place pour l'optimisation statique. Les algorithmes de chiffrement particulièrement bas, car ils reposent généralement sur des calculs numériques énormes, ce qui représente un gain énorme pour les langages d'expédition statiques.

En fait, j'ai été surpris car 40% semble trop petit. Je m'attendais à beaucoup plus. Quoi qu'il en soit, ceci est la version initiale, et je pense que l'optimisation n'était pas la préoccupation principale. Swift n'est même pas complet! Ils vont le rendre meilleur.

Mise à jour

Certains n'arrêtent pas de me faire dire que la technologie du GC est supérieure. Bien que les éléments ci-dessous puissent être discutés, et juste mon opinion très biaisée, mais je pense que je dois dire pour éviter cet argument inutile.

Je sais ce que sont les GC conservateurs / traçage / génération / incrémental / parallèle / temps réel et en quoi ils sont différents. Je pense que la plupart des lecteurs le savent aussi déjà. Je conviens également que GC est très utile dans certains domaines et affiche également un débit élevé dans certains cas.

Quoi qu'il en soit, je soupçonne que le débit du GC est toujours supérieur au RC. La majeure partie des frais généraux de RC provient de l'opération de décompte et du verrouillage pour protéger la variable du nombre de ref. Et la mise en œuvre de la RC fournit généralement un moyen d’éviter les opérations de comptage. En Objective-C, il y a __unsafe_unretainedet en Swift (bien que ce ne soit toujours pas clair pour moi) des unownedtrucs. Si le coût de l'opération de recomptage n'est pas acceptable, vous pouvez essayer de les exclure de manière sélective en utilisant les mécanismes. Théoriquement, nous pouvons simuler un scénario de propriété presque unique en utilisant des références non conservées de manière très agressive afin d'éviter les frais généraux liés aux RC. Je pense aussi que le compilateur peut éliminer automatiquement certaines opérations évidentes et inutiles de la télécommande.

Contrairement au système RC, AFAIK, la désactivation partielle des types de référence n’est pas une option sur le système GC.

Je sais que de nombreux graphismes et jeux publiés utilisent un système basé sur GC, et que la plupart d’entre eux souffrent du manque de déterminisme. Non seulement pour les caractéristiques de performance, mais aussi pour la gestion de la durée de vie des objets. Unity est principalement écrit en C ++, mais la minuscule partie C # cause tous les problèmes de performances étranges. Des applications hybrides HTML et qui souffrent encore de pics imprévisibles sur n’importe quel système. Largement utilisé ne veut pas dire que c'est supérieur. Cela signifie simplement que c'est facile et populaire pour les personnes qui n'ont pas beaucoup d'options.

Mise à jour 2

Encore une fois, pour éviter des discussions ou des discussions inutiles, j’ajoute quelques détails supplémentaires.

@Asik a fourni un avis intéressant sur les pointes de GC. Nous pouvons considérer l’ approche axée sur le type de valeur pour tous les utilisateurs comme un moyen de se soustraire au contenu du GC. Ceci est très attrayant, et même réalisable sur certains systèmes (approche purement fonctionnelle par exemple). Je suis d'accord que c'est bien en théorie. Mais dans la pratique, il y a plusieurs problèmes. Le plus gros problème est que l'application partielle de cette astuce ne fournit pas de véritables caractéristiques sans pointe.

Parce que le problème de latence est toujours un problème tout ou rien . Si vous avez un pic d'image pendant 10 secondes (= 600 images), alors tout le système échoue. Ce n'est pas à propos de savoir comment mieux ou pire. C'est juste réussir ou échouer. (ou moins de 0,0001%) Alors où est la source de pic de GC? C'est une mauvaise distribution de la charge GC. Et c'est parce que le GC est fondamentalement indéterministe. Si vous faites des ordures, cela activera le CPG et le pic atteindra éventuellement. Bien sûr, dans le monde idéal où la charge GC sera toujours idéale, cela ne se produira pas, mais je vis dans le monde réel plutôt que dans un monde idéal imaginaire.

Ensuite, si vous voulez éviter les pointes, vous devez supprimer tous les types de références de l'ensemble du système. Mais c’est difficile, insensé et même impossible en raison de composants inamovibles tels que le système central .NET et la bibliothèque. Utiliser simplement un système non GC est beaucoup plus facile .

Contrairement à GC, la RC est fondamentalement déterministe, et vous n'avez pas à utiliser cette optimisation insensée (purement du type valeur uniquement) pour vous contenter d'éviter le pic. Ce que vous devez faire est de rechercher et d’optimiser la partie qui cause le pic. Dans les systèmes RC, la pointe est un problème d'algorithme local, mais dans les systèmes GC, les pointes sont toujours une question de système global.

Je pense que ma réponse est trop éloignée du sujet et consiste principalement en une répétition des discussions existantes. Si vous voulez vraiment revendiquer une supériorité / infériorité / alternative ou tout autre élément de contenu GC / RC, les discussions sur ce site et StackOverflow sont nombreuses, et vous pouvez continuer à vous battre.

Eonil
la source
4
La collecte des ordures, en particulier générationnelle, est généralement beaucoup plus rapide que le comptage des références.
Jan Hudec
9
@JanHudec Votre vitesse nettement plus rapide n'a tout simplement pas de sens dans le domaine graphique en temps réel. C'est pourquoi je mentionne que des progrès considérables sont nécessaires sur GC. Le GC générationnel n’est même pas proche d’être exempt de pics, tant théoriquement que pratiquement.
Eonil
5
Plus rapide et sans pointe sont des catégories complètement orthogonales. Les éboueurs de génération sont plus rapides . Ils ne sont pas libres.
Jan Hudec
4
Vous parlez de débit . Plus rapide a toujours été un terme vague et peut signifier n'importe quoi selon le contexte. Si vous souhaitez discuter de la signification des termes, vous devez utiliser un terme plus précis plutôt que plus rapide, en particulier si vous tenez compte du contexte actuel - graphiques en temps réel.
Eonil
11
@JanHudec: Sur les appareils mobiles, ou sur tout appareil aux ressources limitées, le GC n'est pas beaucoup plus rapide et constitue en fait une partie importante du problème.
Mason Wheeler
72

Étant 3,9 fois plus rapide que le python, le langage qui perd systématiquement la plupart des points de repère (ok, c’est à égalité avec Perl, Ruby et PHP; mais il perd tout ce qui est typé de manière statique), n’est pas une chose à laquelle on devrait se vanter.

Le jeu de tests de performances montre les programmes C ++ qui sont plus rapides que les programmes python dans la plupart des cas. Ce n'est pas beaucoup mieux quand on compare avec Java, C # (sur Mono), OCaml, Haskell et même Clojure, qui n'est pas typé statiquement.

La vraie question est donc de savoir comment Objective-C n’est que 2,8 fois plus rapide que python. Apparemment, ils ont soigneusement choisi le repère où la répartition lente et complètement dynamique d’ObjC fait très mal. Toute langue typée statiquement devrait pouvoir faire mieux. Dans le type d'objet complexe, il existe de nombreux appels de méthodes pour comparer les objets et la comparaison réelle n'était probablement pas très complexe en soi. Donc, si Swift tire au moins parti des informations de type, il peut facilement faire mieux sur les appels de méthode et il n’ya pas assez d’autres opérations dans lesquelles ObjC pourrait être meilleur.

Bien sûr, comme le montre clairement le jeu des repères , les performances relatives des tâches varient énormément. Un repère n’est donc pas vraiment représentatif. S'ils avaient des points de repère où ils avaient un avantage plus grand, ils nous auraient montré celui-là à la place, alors pour d'autres tâches, ce n'est probablement pas mieux ou pas tellement.

Jan Hudec
la source
13
Je ne comprends pas très bien le but de cette réponse. Êtes-vous en train de répondre "comment va plus vite" en disant "les repères sont imparfaits"? Est-ce ce que vous voulez dire? Je ne vois pas comment cela répond à ce qui était demandé.
Bryan Oakley
15
@ BryanOakley: Je ne pense pas que les points de repère soient imparfaits, mais la possibilité qu'ils aient choisi celui où Swift était le plus rapide doit certainement être envisagée.
Jan Hudec
23
Il est possible que la réponse à "Comment va Swift plus vite?" pourrait être "Ce n'est pas, en fait", @BryanOakley; c'est l'essentiel de la réponse de Jan que je comprends. "Mensonges, maudits mensonges et statistiques", après tout.
Josh Caswell
4
Il y a quelque temps, nous avions déjà comparé Codename One sous iOS et notre implémentation Java était bien plus rapide qu'Objective-C codenameone.com/blog/. Jan est correct, la répartition dynamique est très lente. montrer une énorme amélioration. S'ils améliorent l'ARC même d'une fraction (grâce à une meilleure analyse du code), ils peuvent se débarrasser d'une complexité ridicule. Plus le langage utilisé est restreint, plus le compilateur peut optimiser (voir Java) et Swift ajoute des restrictions.
Shai Almog
7
La réponse de Jan est une réponse parfaite au Q1 et probablement au Q2. Quand j'ai vu les points de repère d'un événement marketing comme discours principal, j'ai pensé: "Waouh, seulement 1,3x dans le meilleur des cas. Quel sera le résultat moyen? 0,3x?"
Amin Negm-Awad Le
5

Objective-C distribue dynamiquement chaque appel de méthode.

Hypothèse: Le benchmark utilise le typage statique pour laisser le compilateur Swift compareextraire la recherche de méthode de la sortboucle. Cela nécessite une restriction de type étroite qui n'autorise que les objets complexes du tableau, pas les sous-classes de complexes.

(En Objective-C, vous pouvez lever manuellement la recherche de méthode si vous le souhaitez, en appelant le support d’exécution de la langue pour rechercher le pointeur de la méthode. Vous feriez mieux de vous assurer que toutes les occurrences du tableau appartiennent à la même classe. .)

Hypothèse: Swift optimise les appels de comptage de références en dehors de la boucle.

Hypothèse: le test de référence Swift utilise une structure complexe à la place d'un objet Objective-C. Les comparaisons de tri n'ont donc pas besoin de dépêches de méthodes dynamiques (car elles ne peuvent pas être sous-classées) ni de travail de comptage de références (puisqu'il s'agit d'un type de valeur).

(Dans Objective-C, vous pouvez utiliser C / C ++ pour améliorer les performances tant qu'il ne concerne pas les objets Objective-C, par exemple, triez un tableau C de structures.)

Jerry101
la source
3

Honnêtement, à moins qu’ils ne publient la source des tests qu’ils utilisent, je ne ferais pas confiance à tout ce que Apple aurait à dire sur le sujet. Rappelez-vous que c’est la société qui est passée de PPC à Intel en raison de problèmes d’alimentation, alors que 6 mois plus tôt, ils disaient qu’Intel avait aspiré et incendié le lapin Intel dans une publicité. J'aimerais voir une preuve irréfutable irréfutable que Swift est plus rapide qu'ObjC dans plus de catégories que le simple tri.

En outre, vous devez vous interroger sur les statistiques publiées par WWDC, qui ont l'odeur du marketing.

Tout cela étant dit, je n'ai pas fait de test entre swift et ObjC, mais d'après ce que je sais, swift possède ses propres extensions IR LLVM et il est possible qu'une optimisation plus importante soit réalisée au moment de la compilation par rapport à ObjC.

Full Disclosure: J'écris un compilateur Swift open source situé à l' adresse https://ind.ie/phoenix/

Si quelqu'un souhaite s’assurer que Swift n’est pas uniquement disponible sur le matériel Apple, faites-le-moi savoir et je me ferai un plaisir de vous inclure.

greg.casamento
la source
2
cela se lit plus comme un commentaire ridicule, voir Comment répondre
Gnat
2
Est-ce mieux maintenant? :)
greg.casamento
0

J'ai moi-même eu du mal à suivre le didacticiel Swift et il me semble que Swift est plus terre à terre (me fait penser à Visual Basic) avec moins d'objectivation que Objective-C. S'ils avaient pris en compte C ou C ++, je suppose que ce dernier aurait gagné, car ils sont encore plus compiles.

Dans ce cas, je suppose que Objective-C est victime de sa pureté orientée objet (et de son overhead).

Noir peint
la source
13
Faire un benchmark "type d'objet complexe" serait un peu difficile dans un langage tel que C qui n'a pas d'implémentation native des objets. Étant donné que l'auditoire de cette conférence était probablement composé à 100% de programmeurs Objective-C, la comparaison avec un langage comme le C ++ n'a pas beaucoup de sens non plus. Le but de Swift n'est pas "hé, c'est la plus grande langue de tous les temps!" mais plutôt "hé, c’est plus rapide que le langage que vous utilisez maintenant pour le développement OSX / iOS".
Bryan Oakley
10
C a une amende parfaite qsortqui permettra le tri d’objets complexes; il utilise simplement un rappel qui comprend les objets à portée de main. Je suppose que C ++ est manquant car std::sortcela gênerait Swift. (Puisqu'il s'agit d'un modèle, un compilateur C ++ peut fortement l'optimiser, jusqu'au déroulement de la boucle.)
MSalters
@MSalters: Je suis entièrement d'accord avec vous. C et C ++ ont tous deux la capacité de dépasser Swift. Serait-il possible d'obtenir le test exécuté. Je suis plus que disposé à exécuter le même critère avec Swift, Objective-C, C ++ et C.
Painted Black
@ BryanOakley également, "Cette langue nécessite moins de crochets!"
Nick Bedford
1
Cette réponse ne tient pas du tout de l'eau et est terriblement trompeuse. OO n’est pas vraiment lent, en fait, les systèmes les plus rapides que vous trouverez autour de vous seront C ++, Java et C # et le style de programmation (fortement OO ou non) aura très peu à voir avec les vitesses résultantes à moins que vous ayez vraiment mauvais code.
Bill K