Apple hat auf der WWDC14 seine neue Programmiersprache Swift vorgestellt . In der Präsentation wurden einige Leistungsvergleiche zwischen Objective-C und Python durchgeführt. Das Folgende ist ein Bild von einer ihrer Folien, von einem Vergleich dieser drei Sprachen, die eine komplexe Objektsortierung durchführen:
Es gab ein noch unglaublicheres Diagramm über einen Leistungsvergleich unter Verwendung des RC4- Verschlüsselungsalgorithmus.
Offensichtlich ist dies ein Marketinggespräch, und sie gingen nicht im Detail darauf ein, wie dies in jedem umgesetzt wurde. Ich frage mich allerdings:
- Wie kann eine neue Programmiersprache so viel schneller sein?
- Werden die Objective-C-Ergebnisse von einem fehlerhaften Compiler verursacht oder ist in Objective-C etwas weniger effizient als in Swift?
- Wie würden Sie eine 40% ige Leistungssteigerung erklären? Ich verstehe, dass die Speicherbereinigung / automatische Referenzkontrolle zusätzlichen Aufwand verursachen kann, aber so viel?
Antworten:
Erstens ist (IMO) ein Vergleich mit Python nahezu bedeutungslos. Nur der Vergleich mit Objective-C ist sinnvoll.
Objective-C ist eine langsame Sprache. (Nur C ist schnell, aber das liegt daran, dass es C ist.) Es war noch nie extrem schnell. Es war gerade schnell genug für ihren (Apples) Zweck und schneller als ihre älteren Versionen. Und es war langsam, weil ...
Objective-C garantierte, dass jede Methode dynamisch versendet wurde. Kein statischer Versand. Das machte es unmöglich, ein Objective-C-Programm weiter zu optimieren. Nun, vielleicht kann JIT-Technologie eine Hilfe sein, aber AFAIK, Apple hasst wirklich unvorhersehbare Leistungsmerkmale und Objektlebensdauer. Ich glaube nicht, dass sie irgendwelche JIT-Sachen übernommen hatten. Swift hat keine solche Garantie für den dynamischen Versand, es sei denn, Sie legen ein spezielles Attribut für die Objective-C-Kompatibilität fest.
GC oder RC spielt hier keine Rolle. Swift beschäftigt ebenfalls hauptsächlich RC. Kein GC ist da und wird es auch nicht, es sei denn, es gibt einen großen architektonischen Sprung in der GC-Technologie. (IMO, es ist für immer) Ich glaube, Swift hat viel mehr Raum für statische Optimierung. Insbesondere Verschlüsselungsalgorithmen auf niedriger Ebene, die normalerweise auf umfangreichen numerischen Berechnungen beruhen, sind für statisch versandte Sprachen von großem Vorteil.
Eigentlich war ich überrascht, weil 40% zu klein scheinen. Ich habe viel mehr erwartet. Auf jeden Fall ist dies die erste Veröffentlichung, und ich denke, die Optimierung war nicht das Hauptanliegen. Swift ist noch nicht einmal komplett! Sie werden es besser machen.
Aktualisieren
Einige nerven mich, wenn sie behaupten, dass die GC-Technologie überlegen ist. Die folgenden Dinge können zwar strittig sein und sind nur meine voreingenommene Meinung, aber ich denke, ich muss sagen, um dieses unnötige Argument zu vermeiden.
Ich weiß, was konservative / Rückverfolgungs- / generationsbezogene / inkrementelle / parallele / Echtzeit-GCs sind und wie sie sich unterscheiden. Ich denke, die meisten Leser wissen das auch schon. Ich stimme auch zu, dass GC in einigen Bereichen sehr gut ist und in einigen Fällen auch einen hohen Durchsatz aufweist.
Ich vermute jedenfalls, dass die Behauptung des GC-Durchsatzes immer besser ist als die von RC. Der größte Teil des RC-Overheads stammt aus dem Nachzählen und Sperren, um die Variable für die Nachzählungsnummer zu schützen. Und die RC-Implementierung bietet normalerweise eine Möglichkeit, Zählvorgänge zu vermeiden. In Objective-C gibt es
__unsafe_unretained
und in Swift (obwohl es für mich immer noch etwas unklar ist)unowned
Dinge. Wenn die Kosten für die Nachzählung nicht akzeptabel sind, können Sie versuchen, sie mithilfe der Mechanik selektiv zu deaktivieren. Theoretisch können wir ein fast einzigartiges Besitzerszenario simulieren, indem wir nicht beibehaltene Referenzen sehr aggressiv verwenden, um einen RC-Overhead zu vermeiden. Außerdem erwarte ich, dass der Compiler einige offensichtlich unnötige RC-Operationen automatisch eliminieren kann.Anders als beim RC-System AFAIK ist das teilweise Deaktivieren von Referenztypen beim GC-System keine Option.
Ich weiß, dass es viele veröffentlichte Grafiken und Spiele gibt, die ein GC-basiertes System verwenden, und ich weiß auch, dass die meisten von ihnen unter mangelndem Determinismus leiden. Nicht nur für Leistungsmerkmale, sondern auch für die Verwaltung der Objektlebensdauer. Unity wird hauptsächlich in C ++ geschrieben, aber der winzige C # -Teil verursacht alle merkwürdigen Leistungsprobleme. HTML-Hybrid-Apps und immer noch von unvorhersehbaren Spitzen auf jedem System betroffen. Weit verbreitet bedeutet nicht, dass das überlegen ist. Es bedeutet nur, dass dies für Menschen, die nicht viele Möglichkeiten haben, einfach und beliebt ist.
Update 2
Um unnötige Auseinandersetzungen oder Diskussionen zu vermeiden, füge ich noch einige Details hinzu.
@Asik lieferte eine interessante Meinung zu GC-Spikes. Das heißt, wir können Value-Type-Anywhere- Ansätze als eine Möglichkeit betrachten, GC-Inhalte zu deaktivieren. Dies ist sehr attraktiv und auf einigen Systemen sogar möglich (zum Beispiel rein funktionaler Ansatz). Ich stimme zu, dass dies theoretisch nett ist. In der Praxis gibt es jedoch mehrere Probleme. Das größte Problem ist, dass die teilweise Anwendung dieses Tricks keine echten spitzenfreien Eigenschaften bietet.
Weil Latenzprobleme immer alles oder nichts sind . Wenn Sie 10 Sekunden lang einen Frame-Spike haben (= 600 Frames), fällt offensichtlich das gesamte System aus. Es geht nicht darum, wie besser oder schlechter. Es ist nur bestanden oder nicht bestanden. (oder weniger als 0,0001%) Wo ist dann die Quelle der GC-Spitze? Das ist eine schlechte Verteilung der GC-Last. Und das liegt daran, dass der GC grundsätzlich unbestimmt ist. Wenn Sie irgendeinen Müll machen, wird der GC aktiviert, und irgendwann kommt es zu einem Spike. Natürlich wird dies in der idealen Welt, in der die GC-Last immer ideal ist, nicht passieren, aber ich lebe in der realen Welt und nicht in der imaginären idealen Welt.
Wenn Sie Spitzen vermeiden möchten, müssen Sie alle Ref-Typen aus dem gesamten System entfernen . Aber es ist schwierig, verrückt und sogar unmöglich, da Teile wie das .NET-Kernsystem und die Bibliothek nicht entfernbar sind. Die Verwendung eines Nicht-GC-Systems ist weitaus einfacher .
Im Gegensatz zu GC ist RC grundsätzlich deterministisch, und Sie müssen diese verrückte Optimierung (nur für den Werttyp) nicht verwenden, nur um Spitzen zu vermeiden. Was Sie tun müssen, ist das Aufspüren und Optimieren des Teils, das die Spitze verursacht. In RC-Systemen ist Spike ein lokales Algorithmusproblem, in GC-Systemen sind Spikes jedoch immer ein globales Systemproblem.
Ich denke, meine Antwort ist zu weit vom Thema entfernt und besteht hauptsächlich aus der Wiederholung bestehender Diskussionen. Wenn Sie wirklich eine Überlegenheit / Unterlegenheit / Alternative oder irgendetwas anderes von GC / RC-Zeug behaupten möchten, gibt es auf dieser Site und in StackOverflow viele Diskussionen, und Sie können dort weiter kämpfen.
quelle
Die Sprache ist 3,9-mal schneller als Python und verliert durchweg die meisten Benchmarks.
Das Benchmarks-Spiel zeigt C ++ - Programme, die in den meisten Fällen um eine Größenordnung schneller sind als Python-Programme. Im Vergleich zu Java, C # (auf Mono), OCaml, Haskell und sogar Clojure, die nicht statisch typisiert sind, ist es nicht viel besser.
Die eigentliche Frage ist also, wie ist Objective-C nur 2,8-mal schneller als Python. Anscheinend wählten sie sorgfältig den Benchmark, bei dem der langsame, voll dynamische Versand von ObjC sehr weh tut. Jede statisch typisierte Sprache sollte es besser können. Bei der komplexen Objektsortierung gibt es viele Methodenaufrufe zum Vergleichen der Objekte, und der tatsächliche Vergleich selbst war wahrscheinlich nicht sehr komplex. Wenn Swift also die Typinformationen zumindest teilweise nutzt, kann es die Methodenaufrufe leicht verbessern, und es gibt nicht genügend andere Operationen, in denen ObjC besser sein könnte.
Wie das Benchmark-Spiel deutlich zeigt, ist die relative Leistung bei verschiedenen Aufgaben natürlich sehr unterschiedlich, so dass ein Benchmark nicht wirklich repräsentativ ist. Wenn sie einen Benchmark hätten, bei dem es einen größeren Vorteil hätte, hätten sie uns stattdessen diesen gezeigt, also ist es bei anderen Aufgaben wahrscheinlich nicht besser oder nicht so viel.
quelle
Objective-C löst jeden Methodenaufruf dynamisch aus.
Hypothese: Der Benchmark verwendet statische Typisierung, damit der Swift-Compiler die
compare
Methodensuche aus dersort
Schleife herausholt. Dies erfordert eine enge Typeinschränkung, die nur komplexe Objekte im Array zulässt, keine Unterklassen von Complex.(In Objective-C können Sie die Methodensuche manuell starten, wenn Sie dies wirklich möchten. Rufen Sie dazu die Sprachlaufzeitunterstützung auf, um den Methodenzeiger nachzuschlagen. Stellen Sie sicher, dass alle Instanzen im Array derselben Klasse angehören .)
Hypothese: Swift optimiert die Referenzzählung von Anrufen außerhalb der Schleife.
Hypothese: Der Swift-Benchmark verwendet eine komplexe Struktur anstelle eines Objective-C-Objekts, sodass Sortiervergleiche weder dynamische Methodenversendungen (da keine Unterklassen möglich sind) noch Referenzzählarbeiten (da es sich um einen Werttyp handelt) erfordern.
(In Objective-C können Sie für die Leistung auf C / C ++ zurückgreifen, sofern es sich nicht um Objective-C-Objekte handelt, z. B. um das Sortieren eines C-Arrays von Strukturen.)
quelle
Ehrlich gesagt, wenn sie die Quelle nicht für die von ihnen verwendeten Tests freigeben, würde ich nichts vertrauen, was Apple zu diesem Thema zu sagen hat. Denken Sie daran, dies ist das Unternehmen, das aus Stromgründen von PPC zu Intel gewechselt ist, als 6 Monate zuvor behauptet wurde, Intel habe den Intel-Hasen in einem Werbespot gelutscht und tatsächlich angezündet. Ich würde gerne einen unwiderlegbaren Beweis dafür sehen, dass Swift in mehr Kategorien schneller als ObjC ist als nur beim Sortieren.
Außerdem müssen Sie alle Statistiken, die bei WWDC veröffentlicht werden, in Frage stellen, da sie den Geruch von Marketing überall auf sich wirken lassen.
Abgesehen davon habe ich selbst keine Tests zwischen swift und ObjC durchgeführt, aber meines Wissens hat swift seine eigenen LLVM-IR-Erweiterungen und es ist möglich, dass zur Kompilierungszeit mehr Optimierungen durchgeführt werden als in ObjC.
Vollständige Offenlegung: Ich schreibe einen Open-Source-Swift-Compiler unter https://ind.ie/phoenix/
Wenn jemand mithelfen möchte, sicherzustellen, dass Swift nicht nur auf Apple-Hardware verfügbar ist, lassen Sie es mich wissen, und ich würde Sie gerne einbeziehen.
quelle
Ich habe mich durch das Swift-Tutorial gekämpft, und es scheint mir, dass Swift bodenständiger ist (ich denke an Visual Basic), mit weniger 'Objektifizierung' als Objective-C. Hätten sie C oder C ++ berücksichtigt, hätte letzteres vermutlich gewonnen, da sie nur noch mehr Kompilierungszeit haben.
In diesem Fall gehe ich davon aus, dass Objective-C das Opfer der objektorientierten Reinheit (und des Overheads) ist.
quelle
qsort
die eine komplexe Objektsortierung ermöglicht. Es wird nur ein Rückruf verwendet, der die vorhandenen Objekte versteht. Ich vermute, C ++ fehlt, weilstd::sort
es Swift in Verlegenheit bringen würde. (Da es sich um eine Vorlage handelt, kann ein C ++ - Compiler diese stark optimieren, bis die Schleife wieder