Nach meinem Verständnis erzeugt C / C ++ nativen Code, der auf einer bestimmten Maschinenarchitektur ausgeführt werden kann. Umgekehrt laufen Sprachen wie Java und C # auf einer virtuellen Maschine, die die native Architektur abstrahiert. Logischerweise scheint es Java oder C # aufgrund dieses Zwischenschritts unmöglich zu sein, die Geschwindigkeit von C ++ zu erreichen. Mir wurde jedoch gesagt, dass die neuesten Compiler ("Hot Spot") diese Geschwindigkeit erreichen oder sogar überschreiten können.
Vielleicht ist dies eher eine Compiler-Frage als eine Sprachfrage, aber kann jemand im Klartext erklären, wie eine dieser Sprachen der virtuellen Maschine eine bessere Leistung als eine Muttersprache erzielen kann?
Antworten:
Im Allgemeinen können C # und Java genauso schnell oder schneller sein, da der JIT-Compiler - ein Compiler, der Ihre IL bei der ersten Ausführung kompiliert - Optimierungen vornehmen kann, die ein C ++ - kompiliertes Programm nicht kann, weil es den Computer abfragen kann. Es kann feststellen, ob es sich bei der Maschine um Intel oder AMD handelt. Pentium 4, Core Solo oder Core Duo; oder wenn SSE4 usw. unterstützt wird.
Ein C ++ - Programm muss normalerweise vorher mit gemischten Optimierungen kompiliert werden, damit es auf allen Computern anständig läuft, aber nicht so stark optimiert ist, wie es für eine einzelne Konfiguration (dh Prozessor, Befehlssatz, andere Hardware) sein könnte.
Darüber hinaus ermöglichen bestimmte Sprachfunktionen dem Compiler in C # und Java, Annahmen über Ihren Code zu treffen, die es ihm ermöglichen, bestimmte Teile zu optimieren, die für den C / C ++ - Compiler einfach nicht sicher sind. Wenn Sie Zugriff auf Zeiger haben, gibt es viele Optimierungen, die einfach nicht sicher sind.
Auch Java und C # können Heap-Zuweisungen effizienter als C ++ durchführen, da die Abstraktionsebene zwischen dem Garbage Collector und Ihrem Code es ermöglicht, die gesamte Heap-Komprimierung auf einmal durchzuführen (eine ziemlich teure Operation).
Jetzt kann ich in diesem nächsten Punkt nicht für Java sprechen, aber ich weiß, dass C # beispielsweise tatsächlich Methoden und Methodenaufrufe entfernt, wenn es weiß, dass der Hauptteil der Methode leer ist. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden.
Wie Sie sehen, gibt es viele Gründe, warum bestimmte C # - oder Java-Implementierungen schneller sind.
Nun können in C ++ spezifische Optimierungen vorgenommen werden, die alles wegblasen, was Sie mit C # tun können, insbesondere im Grafikbereich und immer dann, wenn Sie sich in der Nähe der Hardware befinden. Zeiger wirken hier Wunder.
Je nachdem, was Sie schreiben, würde ich mit dem einen oder anderen gehen. Aber wenn Sie etwas schreiben, das nicht hardwareabhängig ist (Treiber, Videospiel usw.), würde ich mir keine Sorgen um die Leistung von C # machen (ich kann wieder nicht über Java sprechen). Es wird gut gehen.
Auf der Java-Seite weist @Swati auf einen guten Artikel hin:
https://www.ibm.com/developerworks/library/j-jtp09275
quelle
JIT vs. Static Compiler
Wie bereits in den vorherigen Beiträgen erwähnt, kann JIT IL / Bytecode zur Laufzeit in nativen Code kompilieren. Die Kosten dafür wurden erwähnt, aber nicht zu dem Schluss:
JIT hat ein großes Problem: Es kann nicht alles kompilieren: Das Kompilieren von JIT braucht Zeit, daher kompiliert das JIT nur einige Teile des Codes, während ein statischer Compiler eine vollständige native Binärdatei erzeugt: Für einige Programme die statische Der Compiler übertrifft die JIT einfach leicht.
Natürlich ist C # (oder Java oder VB) normalerweise schneller, um eine tragfähige und robuste Lösung zu erstellen als C ++ (schon allein deshalb, weil C ++ eine komplexe Semantik aufweist und die C ++ - Standardbibliothek zwar interessant und leistungsfähig ist, aber im Vergleich zur vollständigen Bibliothek ziemlich schlecht Umfang der Standardbibliothek von .NET oder Java), daher ist der Unterschied zwischen C ++ und .NET oder Java JIT für die meisten Benutzer normalerweise nicht sichtbar, und für die kritischen Binärdateien können Sie weiterhin die C ++ - Verarbeitung aufrufen von C # oder Java (auch wenn diese Art von nativen Aufrufen an sich ziemlich kostspielig sein kann) ...
C ++ - Metaprogrammierung
Beachten Sie, dass Sie normalerweise C ++ - Laufzeitcode mit dem entsprechenden Code in C # oder Java vergleichen. C ++ verfügt jedoch über eine Funktion, die Java / C # sofort übertreffen kann, nämlich das Metaprogrammieren von Vorlagen: Die Codeverarbeitung erfolgt zur Kompilierungszeit (wodurch die Kompilierungszeit erheblich verlängert wird), was zu einer Laufzeit von null (oder fast null) führt.
Ich habe noch keinen realen Effekt darauf gesehen (ich habe nur mit Konzepten gespielt, aber bis dahin war der Unterschied Sekunden der Ausführung für JIT und Null für C ++), aber dies ist erwähnenswert, neben der Tatsache, dass Metaprogrammierung nicht der Fall ist trivial......
Native C ++ - Speichernutzung
C ++ hat eine andere Speichernutzung als Java / C # und daher unterschiedliche Vorteile / Mängel.
Unabhängig von der JIT-Optimierung ist nichts so schnell wie der direkte Zeigerzugriff auf den Speicher (ignorieren wir für einen Moment Prozessor-Caches usw.). Wenn Sie also zusammenhängende Daten im Speicher haben, geht der Zugriff auf diese über C ++ - Zeiger (dh C-Zeiger ... Geben wir Caesar die Schuld) schneller als in Java / C #. Und C ++ hat RAII, was die Verarbeitung erheblich vereinfacht als in C # oder sogar in Java. C ++ muss
using
die Existenz seiner Objekte nicht erfassen . Und C ++ hat keinefinally
Klausel. Dies ist kein Fehler.:-)
Und trotz C # -primitiver Strukturen kosten C ++ "on the stack" -Objekte bei Zuweisung und Zerstörung nichts und benötigen keinen GC, um in einem unabhängigen Thread für die Bereinigung zu arbeiten.
Was die Speicherfragmentierung betrifft, so sind Speicherzuordnungen im Jahr 2008 nicht die alten Speicherzuordnungen aus dem Jahr 1980, die normalerweise mit einer GC: C ++ - Zuweisung verglichen werden. Sie können zwar nicht in den Speicher verschoben werden, aber wie bei einem Linux-Dateisystem: Wer benötigt eine Festplatte? Defragmentierung, wenn keine Fragmentierung stattfindet? Die Verwendung des richtigen Allokators für die richtige Aufgabe sollte Teil des C ++ - Entwickler-Toolkits sein. Das Schreiben von Allokatoren ist nicht einfach, und dann haben die meisten von uns bessere Dinge zu tun, und für die meisten Anwendungen ist RAII oder GC mehr als gut genug.
Jetzt wird das Speichermodell mit dem Aufkommen der Multicore- und Multithreading-Technologie etwas komplizierter. In diesem Bereich hat .NET wohl den Vorteil, und Java hat, wie mir gesagt wurde, die Oberhand behalten. Für einige "on the bare metal" -Hacker ist es einfach, seinen Code "in der Nähe der Maschine" zu loben. Jetzt ist es jedoch schwieriger, eine bessere Assembly von Hand zu erstellen, als den Compiler seiner Arbeit zu überlassen. Für C ++ wurde der Compiler seit einem Jahrzehnt normalerweise besser als der Hacker. Für C # und Java ist dies noch einfacher.
Der neue Standard C ++ 0x wird C ++ - Compilern jedoch ein einfaches Speichermodell auferlegen, das effektiven Multiprozessor- / Parallel- / Threading-Code in C ++ standardisiert (und damit vereinfacht) und Optimierungen für Compiler einfacher und sicherer macht. Aber dann werden wir in ein paar Jahren sehen, ob seine Versprechen eingehalten werden.
C ++ / CLI vs. C # / VB.NET
Hinweis: In diesem Abschnitt geht es um C ++ / CLI, dh das von .NET gehostete C ++, nicht das native C ++.
Letzte Woche hatte ich eine Schulung zur .NET-Optimierung und stellte fest, dass der statische Compiler sowieso sehr wichtig ist. So wichtig wie JIT.
Der gleiche Code, der in C ++ / CLI kompiliert wurde (oder sein Vorgänger, Managed C ++), kann zeitweise schneller sein als der gleiche Code, der in C # (oder VB.NET, dessen Compiler dieselbe IL als C # erzeugt) erzeugt wurde.
Weil der statische C ++ - Compiler viel besser war, um bereits optimierten Code zu erzeugen als den von C #.
Beispielsweise ist das Inlining von Funktionen in .NET auf Funktionen beschränkt, deren Bytecode kleiner oder gleich 32 Byte lang ist. Ein Code in C # erzeugt also einen 40-Byte-Accessor, der von der JIT niemals eingebunden wird. Der gleiche Code in C ++ / CLI erzeugt einen 20-Byte-Accessor, der von der JIT eingebunden wird.
Ein weiteres Beispiel sind temporäre Variablen, die einfach vom C ++ - Compiler kompiliert werden, während sie in der vom C # -Compiler erstellten IL noch erwähnt werden. Die statische C ++ - Kompilierungsoptimierung führt zu weniger Code und autorisiert somit erneut eine aggressivere JIT-Optimierung.
Es wurde spekuliert, dass der C ++ / CLI-Compiler von den umfangreichen Optimierungstechniken des nativen C ++ - Compilers profitierte.
Fazit
Ich liebe C ++.
Aber meines Erachtens sind C # oder Java insgesamt eine bessere Wahl. Nicht weil sie schneller als C ++ sind, sondern weil sie, wenn Sie ihre Qualitäten addieren, produktiver sind, weniger Schulung benötigen und vollständigere Standardbibliotheken als C ++ haben. Und wie bei den meisten Programmen sind ihre Geschwindigkeitsunterschiede (auf die eine oder andere Weise) vernachlässigbar ...
Bearbeiten (2011-06-06)
Meine Erfahrung mit C # /. NET
Ich habe jetzt 5 Monate fast ausschließlich professionelle C # -Codierung (was zu meinem Lebenslauf führt, der bereits voll mit C ++ und Java und einem Hauch von C ++ / CLI ist).
Ich habe mit WinForms (Ahem ...) und WCF (cool!) Und WPF (Cool !!!! sowohl über XAML als auch über rohes C # gespielt. WPF ist so einfach, dass Swing meiner Meinung nach einfach nicht damit zu vergleichen ist) und C # 4.0.
Die Schlussfolgerung ist, dass es zwar einfacher / schneller ist, einen Code zu erstellen, der in C # / Java funktioniert als in C ++, es jedoch viel schwieriger ist, einen starken, sicheren und robusten Code in C # (und noch schwieriger in Java) als in C ++ zu erstellen. Gründe gibt es zuhauf, aber es kann zusammengefasst werden durch:
using
ist nicht so einfach und leistungsstark, da das Schreiben korrekter Dispose-Implementierungen schwierig ist ).readonly
und Javafinal
sind nirgends so nützlich wie in C ++const
(es gibt keine Möglichkeit, schreibgeschützte komplexe Daten (z. B. einen Baum von Knoten) in C # ohne großen Aufwand verfügbar zu machen, während dies eine integrierte Funktion von C ++ ist. Unveränderliche Daten sind eine interessante Lösung , aber nicht alles kann unveränderlich gemacht werden, also ist es bei weitem nicht genug ).C # bleibt also eine angenehme Sprache, solange Sie etwas wollen, das funktioniert, aber eine frustrierende Sprache, sobald Sie etwas wollen, das immer und sicher funktioniert.
Java ist noch frustrierender, da es die gleichen Probleme wie C # hat und mehr: Ohne das Äquivalent des
using
Schlüsselworts von C # hat ein sehr erfahrener Kollege von mir zu viel Zeit darauf verwendet, sicherzustellen, dass seine Ressourcen korrekt freigegeben wurden, während dies bei C ++ der Fall wäre war einfach (mit Destruktoren und intelligenten Zeigern).Ich denke also, dass der Produktivitätsgewinn von C # / Java für die meisten Codes sichtbar ist ... bis zu dem Tag, an dem der Code so perfekt wie möglich sein muss. An diesem Tag wirst du Schmerzen kennen. (Sie werden nicht glauben, was von unseren Server- und GUI-Apps verlangt wird ...).
Informationen zu serverseitigem Java und C ++
Ich hielt Kontakt zu den Serverteams (ich habe 2 Jahre unter ihnen gearbeitet, bevor ich zum GUI-Team zurückkehrte) auf der anderen Seite des Gebäudes und lernte etwas Interessantes.
In den letzten Jahren bestand der Trend darin, dass die Java-Server-Apps die alten C ++ - Server-Apps ersetzen sollten, da Java über viele Frameworks / Tools verfügt und einfach zu warten, bereitzustellen usw. usw. ist.
... Bis das Problem der geringen Latenz in den letzten Monaten seinen hässlichen Kopf aufrichtete. Dann haben die Java-Server-Apps, unabhängig von der von unserem erfahrenen Java-Team versuchten Optimierung, einfach und sauber das Rennen gegen den alten, nicht wirklich optimierten C ++ - Server verloren.
Derzeit besteht die Entscheidung darin, die Java-Server für den allgemeinen Gebrauch zu behalten, wenn die Leistung zwar noch wichtig ist, jedoch nicht vom Ziel mit geringer Latenz betroffen ist, und die bereits schnelleren C ++ - Serveranwendungen aggressiv für Anforderungen mit geringer Latenz und extrem geringer Latenz zu optimieren.
Fazit
Nichts ist so einfach wie erwartet.
Java und noch mehr C # sind coole Sprachen mit umfangreichen Standardbibliotheken und Frameworks, in denen Sie schnell codieren können und sehr bald Ergebnisse erzielen.
Wenn Sie jedoch rohe Leistung, leistungsstarke und systematische Optimierungen, starke Compiler-Unterstützung, leistungsstarke Sprachfunktionen und absolute Sicherheit benötigen, machen es Java und C # schwierig, die letzten fehlenden, aber kritischen Qualitätsprozente zu gewinnen, die Sie benötigen, um sich von der Konkurrenz abzuheben.
Es ist, als ob Sie weniger Zeit und weniger erfahrene Entwickler in C # / Java als in C ++ benötigen, um Code mit durchschnittlicher Qualität zu erstellen. In dem Moment, in dem Sie exzellenten bis perfekten Qualitätscode benötigen, war es plötzlich einfacher und schneller, die Ergebnisse zu erhalten direkt in C ++.
Dies ist natürlich meine eigene Wahrnehmung, die möglicherweise auf unsere spezifischen Bedürfnisse beschränkt ist.
Aber genau das passiert heute, sowohl in den GUI-Teams als auch in den serverseitigen Teams.
Natürlich werde ich diesen Beitrag aktualisieren, wenn etwas Neues passiert.
Bearbeiten (22.06.2011)
Quellen:
Bearbeiten (20.09.2011)
Quellen:
quelle
Immer wenn ich über verwaltete oder nicht verwaltete Leistung spreche, möchte ich auf die Serie verweisen, in der Rico (und Raymond) C ++ - und C # -Versionen eines Chinesisch / Englisch-Wörterbuchs verglichen haben. Mit dieser Google-Suche können Sie selbst lesen, aber ich mag Ricos Zusammenfassung.
Für mich ist das Fazit, dass die nicht verwaltete Version 6 Revisionen benötigte, um die verwaltete Version zu übertreffen, die ein einfacher Port des ursprünglichen nicht verwalteten Codes war. Wenn Sie die letzte Leistung benötigen (und die Zeit und das Fachwissen haben, um sie zu erhalten), müssen Sie nicht verwaltet werden, aber für mich werde ich den Vorteil in der Größenordnung nutzen, den ich bei den ersten Versionen gegenüber den 33 habe % Ich gewinne, wenn ich es 6 Mal versuche.
quelle
Die Kompilierung für bestimmte CPU-Optimierungen wird normalerweise überbewertet. Nehmen Sie einfach ein Programm in C ++ und kompilieren Sie es mit der Optimierung für Pentium PRO und führen Sie es auf einem Pentium 4 aus. Dann kompilieren Sie es erneut mit der Optimierung für Pentium 4. Ich habe lange Nachmittage damit verbracht, es mit mehreren Programmen zu tun. Allgemeine Ergebnisse? Normalerweise weniger als 2-3% Leistungssteigerung. Die theoretischen JIT-Vorteile sind also fast keine. Die meisten Leistungsunterschiede können nur bei Verwendung skalarer Datenverarbeitungsfunktionen beobachtet werden. Dies erfordert möglicherweise eine manuelle Feinabstimmung, um ohnehin maximale Leistung zu erzielen. Optimierungen dieser Art sind langsam und kostenintensiv und daher für JIT manchmal sowieso ungeeignet.
In der realen Welt und in realen Anwendungen ist C ++ normalerweise immer noch schneller als Java, hauptsächlich aufgrund des geringeren Speicherbedarfs, der zu einer besseren Cache-Leistung führt.
Um jedoch alle C ++ - Funktionen nutzen zu können, muss der Entwickler hart arbeiten. Sie können überlegene Ergebnisse erzielen, aber dafür müssen Sie Ihr Gehirn einsetzen. C ++ ist eine Sprache, die beschlossen hat, Ihnen mehr Tools zur Verfügung zu stellen, wobei der Preis berechnet wird, den Sie lernen müssen, um die Sprache gut verwenden zu können.
quelle
JIT (Just In Time Compiling) kann unglaublich schnell sein, da es für die Zielplattform optimiert wird.
Dies bedeutet, dass es jeden Compiler-Trick nutzen kann, den Ihre CPU unterstützen kann, unabhängig davon, auf welche CPU der Entwickler den Code geschrieben hat.
Das Grundkonzept der .NET JIT funktioniert folgendermaßen (stark vereinfacht):
Zum ersten Mal eine Methode aufrufen:
Zum zweiten Mal eine Methode aufrufen:
Wie Sie sehen können, ist es beim zweiten Mal praktisch der gleiche Prozess wie in C ++, außer mit dem Vorteil von Echtzeitoptimierungen.
Trotzdem gibt es noch andere Overhead-Probleme, die eine verwaltete Sprache verlangsamen, aber die JIT hilft sehr.
quelle
Ich mag die Antwort von Orion Adrian , aber es gibt noch einen anderen Aspekt.
Die gleiche Frage wurde vor Jahrzehnten über Assemblersprache im Vergleich zu "menschlichen" Sprachen wie FORTRAN gestellt. Und ein Teil der Antwort ist ähnlich.
Ja, ein C ++ - Programm kann mit einem bestimmten (nicht trivialen?) Algorithmus schneller als C # sein, aber das Programm in C # ist häufig genauso schnell oder schneller als eine "naive" Implementierung in C ++ und eine optimierte Version in C ++ Die Entwicklung wird länger dauern und die C # -Version möglicherweise immer noch um einen sehr kleinen Vorsprung übertreffen. Also, ist es das wirklich wert?
Sie müssen diese Frage einzeln beantworten.
Trotzdem bin ich ein langjähriger Fan von C ++ und ich denke, es ist eine unglaublich ausdrucksstarke und mächtige Sprache - manchmal unterschätzt. Aber in vielen "realen" Problemen (für mich persönlich bedeutet das "die Art, für deren Lösung ich bezahlt werde") wird C # die Arbeit schneller und sicherer erledigen.
Die größte Strafe, die Sie zahlen? Viele .NET- und Java-Programme sind Speicherfresser. Ich habe gesehen, dass .NET- und Java-Apps "Hunderte" Megabyte Speicher benötigen, wenn C ++ - Programme mit ähnlicher Komplexität kaum die "Zehn" MBs zerkratzen.
quelle
Ich bin mir nicht sicher, wie oft Sie feststellen werden, dass Java-Code selbst mit Hotspot schneller als C ++ ausgeführt wird, aber ich werde versuchen, zu erklären, wie dies passieren könnte.
Stellen Sie sich kompilierten Java-Code als interpretierte Maschinensprache für die JVM vor. Wenn der Hotspot-Prozessor feststellt, dass bestimmte Teile des kompilierten Codes mehrmals verwendet werden, führt er eine Optimierung des Maschinencodes durch. Da die Hand-Tuning-Assembly fast immer schneller ist als C ++ - kompilierter Code, kann man sich vorstellen, dass programmgesteuerter Maschinencode nicht allzu schlecht sein wird.
Bei sich stark wiederholendem Code konnte ich also sehen, wo Hotspot JVM Java schneller als C ++ ausführen kann ... bis die Garbage Collection ins Spiel kommt. :) :)
quelle
Since hand-tuning Assembly is almost always faster than C++ compiled code
? Was meinen Sie mit "Hand-Tuning Assembly" und "C ++ - kompiliertem Code"?Im Allgemeinen ist der Algorithmus Ihres Programms für die Geschwindigkeit Ihrer Anwendung viel wichtiger als die Sprache . Sie können einen schlechten Algorithmus in jeder Sprache implementieren, einschließlich C ++. In diesem Sinne können Sie im Allgemeinen Code schreiben, der schneller in einer Sprache ausgeführt wird, mit der Sie einen effizienteren Algorithmus implementieren können.
Höhere Sprachen können dies sehr gut, indem sie den Zugriff auf viele effiziente vorgefertigte Datenstrukturen erleichtern und Praktiken fördern, mit denen Sie ineffizienten Code vermeiden können. Natürlich können sie es manchmal auch einfach machen, eine Menge wirklich langsamen Codes zu schreiben, sodass Sie Ihre Plattform immer noch kennen müssen.
Außerdem holt C ++ "neue" Funktionen (beachten Sie die Anführungszeichen) wie STL-Container, automatische Zeiger usw. ein - siehe beispielsweise die Boost-Bibliothek. Und gelegentlich stellen Sie möglicherweise fest, dass der schnellste Weg, um eine Aufgabe zu erledigen, eine Technik wie die Zeigerarithmetik erfordert, die in einer höheren Sprache verboten ist. In der Regel können Sie jedoch eine Bibliothek aufrufen, die in einer Sprache geschrieben ist, die sie wie gewünscht implementieren kann .
Die Hauptsache ist, die Sprache zu kennen, die Sie verwenden, die zugehörige API, was sie kann und welche Einschränkungen sie hat.
quelle
Ich weiß es auch nicht ... meine Java-Programme sind immer langsam. :-) Ich habe jedoch nie wirklich bemerkt, dass C # -Programme besonders langsam sind.
quelle
Hier ist ein weiterer interessanter Benchmark, den Sie selbst auf Ihrem eigenen Computer ausprobieren können.
Es vergleicht ASM, VC ++, C #, Silverlight, Java-Applet, Javascript, Flash (AS3)
Roozz Plugin Speed Demo
Bitte beachten Sie, dass die Geschwindigkeit von Javascript sehr unterschiedlich ist, je nachdem, welcher Browser es ausführt. Gleiches gilt für Flash und Silverlight, da diese Plugins im selben Prozess wie der Hosting-Browser ausgeführt werden. Das Roozz-Plugin führt jedoch Standard-EXE-Dateien aus, die in einem eigenen Prozess ausgeführt werden. Daher wird die Geschwindigkeit nicht vom Hosting-Browser beeinflusst.
quelle
Sie sollten "Leistung besser als .." definieren. Nun, ich weiß, Sie haben nach Geschwindigkeit gefragt, aber es ist nicht alles, was zählt.
Und so weiter, es ist voreingenommen, ja;)
Mit C # und Java zahlen Sie einen Preis für das, was Sie erhalten (schnellere Codierung, automatische Speicherverwaltung, große Bibliothek usw.). Aber Sie haben nicht viel Raum, um über die Details zu feilschen: Nehmen Sie das komplette Paket oder nichts.
Selbst wenn diese Sprachen einen Code so optimieren können, dass er schneller als kompilierter Code ausgeführt wird, ist der gesamte Ansatz (IMHO) ineffizient. Stellen Sie sich vor, Sie fahren jeden Tag 5 Meilen mit einem LKW zu Ihrem Arbeitsplatz! Es ist bequem, es fühlt sich gut an, Sie sind sicher (extreme Knautschzone) und nachdem Sie einige Zeit Gas gegeben haben, ist es sogar so schnell wie ein Standardauto! Warum haben wir nicht alle einen LKW, um zur Arbeit zu fahren? ;)
In C ++ bekommen Sie, wofür Sie bezahlen, nicht mehr und nicht weniger.
Zitat von Bjarne Stroustrup: "C ++ ist meine Lieblingssprache für gesammelten Müll, weil sie so wenig Müll erzeugt" Linktext
quelle
times
auf einer Shell zu wiederholen . Damit wird das gesamte Programm überprüft, nicht nur ein einzelner Aspekt. Sind die Ergebnisse dann ähnlich?Der von einem Java- oder C # -Compiler erzeugte ausführbare Code wird nicht interpretiert - er wird "just in time" (JIT) zu nativem Code kompiliert. Wenn also zum ersten Mal Code in einem Java / C # -Programm während der Ausführung auftritt, entsteht ein gewisser Overhead, da der "Laufzeit-Compiler" (auch bekannt als JIT-Compiler) den Bytecode (Java) oder IL-Code (C #) in native Maschinenanweisungen umwandelt. Wenn dieser Code jedoch das nächste Mal auftritt, während die Anwendung noch ausgeführt wird, wird der native Code sofort ausgeführt. Dies erklärt, wie einige Java / C # -Programme anfangs langsam erscheinen, dann aber eine bessere Leistung erzielen, je länger sie ausgeführt werden. Ein gutes Beispiel ist eine ASP.Net-Website. Beim ersten Zugriff auf die Website kann dies etwas langsamer sein, da der C # -Code vom JIT-Compiler zu nativem Code kompiliert wird.
quelle
Hier einige gute Antworten zu der spezifischen Frage, die Sie gestellt haben. Ich möchte zurücktreten und das Gesamtbild betrachten.
Beachten Sie, dass die Wahrnehmung Ihres Benutzers für die Geschwindigkeit der von Ihnen geschriebenen Software von vielen anderen Faktoren beeinflusst wird, als nur davon, wie gut der Codegen optimiert. Hier sind einige Beispiele:
Manuelle Speicherverwaltung ist schwer korrekt durchzuführen (keine Lecks) und noch schwieriger effizient durchzuführen (freier Speicher, kurz nachdem Sie damit fertig sind). Die Verwendung eines GC führt im Allgemeinen eher zu einem Programm, das den Speicher gut verwaltet. Sind Sie bereit, sehr hart zu arbeiten und die Bereitstellung Ihrer Software zu verzögern, um den GC zu übertreffen?
Mein C # ist leichter zu lesen und zu verstehen als mein C ++. Ich habe auch mehr Möglichkeiten, mich davon zu überzeugen, dass mein C # -Code korrekt funktioniert. Das bedeutet, dass ich meine Algorithmen optimieren kann, ohne dass das Risiko besteht, dass Fehler auftreten (und Benutzer mögen keine Software, die abstürzt, selbst wenn dies schnell geschieht!).
Ich kann meine Software in C # schneller erstellen als in C ++. Das spart Zeit, um an der Leistung zu arbeiten und meine Software trotzdem pünktlich zu liefern.
Es ist einfacher, eine gute Benutzeroberfläche in C # zu schreiben als in C ++, daher bin ich eher in der Lage, die Arbeit in den Hintergrund zu rücken, während die Benutzeroberfläche reagiert, oder eine Fortschritts- oder Hearbeat-Benutzeroberfläche bereitzustellen, wenn das Programm für eine Weile blockiert werden muss. Dies macht nichts schneller, aber es macht Benutzer glücklicher über das Warten.
Alles, was ich über C # gesagt habe, gilt wahrscheinlich für Java. Ich habe einfach nicht die Erfahrung, dies mit Sicherheit zu sagen.
quelle
Wenn Sie ein Java / C # -Programmierer sind, der C ++ lernt, werden Sie versucht sein, weiter in Java / C # zu denken und wörtlich in die C ++ - Syntax zu übersetzen. In diesem Fall erhalten Sie nur die zuvor genannten Vorteile von nativem Code gegenüber interpretiertem / JIT. Um den größten Leistungsgewinn in C ++ im Vergleich zu Java / C # zu erzielen, müssen Sie lernen, in C ++ zu denken und Code speziell zu entwerfen, um die Stärken von C ++ zu nutzen.
Um Edsger Dijkstra zu paraphrasieren : [Ihre Muttersprache] verstümmelt den Geist bis zur Genesung.
Um Jeff Atwood zu paraphrasieren : Sie können [Ihre Muttersprache] in jeder neuen Sprache schreiben.
quelle
Eine der wichtigsten JIT-Optimierungen ist das Inlining von Methoden. Java kann sogar virtuelle Methoden einbinden, wenn es die Laufzeitkorrektheit gewährleisten kann. Diese Art der Optimierung kann normalerweise nicht von statischen Standard-Compilern durchgeführt werden, da eine Analyse des gesamten Programms erforderlich ist, was aufgrund der separaten Kompilierung schwierig ist (im Gegensatz dazu verfügt JIT über das gesamte Programm). Das Inlining von Methoden verbessert andere Optimierungen und bietet größere Codeblöcke zur Optimierung.
Die Standardspeicherzuweisung in Java / C # ist ebenfalls schneller und die Freigabe (GC) ist nicht viel langsamer, sondern nur weniger deterministisch.
quelle
free
unddelete
auch nicht deterministisch sind und GC durch Nichtzuweisung deterministisch gemacht werden kann.Es ist unwahrscheinlich, dass die Sprachen der virtuellen Maschine kompilierte Sprachen übertreffen, aber sie können nahe genug kommen, dass es aus (zumindest) den folgenden Gründen keine Rolle spielt (ich spreche hier für Java, da ich C # noch nie gemacht habe).
1 / Die Java-Laufzeitumgebung ist normalerweise in der Lage, häufig ausgeführte Codeteile zu erkennen und eine Just-in-Time-Kompilierung (JIT) dieser Abschnitte durchzuführen, damit sie in Zukunft mit der vollen kompilierten Geschwindigkeit ausgeführt werden.
2 / Große Teile der Java-Bibliotheken werden kompiliert, sodass Sie beim Aufrufen einer Bibliotheksfunktion kompilierten Code ausführen, der nicht interpretiert wird. Sie können den Code (in C) sehen, indem Sie das OpenJDK herunterladen.
3 / Wenn Sie keine umfangreichen Berechnungen durchführen, wartet Ihr Programm die meiste Zeit auf die Eingabe eines sehr langsamen (relativ gesehen) Menschen.
4 / Da ein Großteil der Validierung des Java-Bytecodes zum Zeitpunkt des Ladens der Klasse erfolgt, wird der normale Aufwand für Laufzeitprüfungen erheblich reduziert.
5 / Im schlimmsten Fall kann leistungsintensiver Code in ein kompiliertes Modul extrahiert und von Java (siehe JNI) aufgerufen werden, damit er mit voller Geschwindigkeit ausgeführt wird.
Zusammenfassend lässt sich sagen, dass der Java-Bytecode niemals die native Maschinensprache übertrifft, aber es gibt Möglichkeiten, dies zu mildern. Der große Vorteil von Java (wie ich es sehe) ist die RIESIGE Standardbibliothek und die plattformübergreifende Natur.
quelle
Orion Adrian , lassen Sie mich Ihren Beitrag umkehren , um zu sehen, wie unbegründet Ihre Bemerkungen sind, denn auch über C ++ kann viel gesagt werden. Und wenn Sie sagen, dass der Java / C # -Compiler leere Funktionen optimiert, klingen Sie wirklich so, als wären Sie nicht mein Experte für Optimierung, denn a) warum sollte ein echtes Programm leere Funktionen enthalten, außer wirklich schlechtem Legacy-Code, b) das ist wirklich nicht so Schwarz- und Blutungskantenoptimierung.
Abgesehen von diesem Satz haben Sie offen über Zeiger geschimpft, aber funktionieren Objekte in Java und C # nicht im Grunde wie C ++ - Zeiger? Dürfen sie sich nicht überschneiden? Dürfen sie nicht null sein? C (und die meisten C ++ - Implementierungen) hat das Schlüsselwort Restrict, beide haben Werttypen, C ++ hat einen Verweis auf den Wert mit einer Garantie ungleich Null. Was bieten Java und C #?
>>>>>>>>>>
Im Allgemeinen können C und C ++ genauso schnell oder schneller sein, da der AOT-Compiler - ein Compiler, der Ihren Code vor der Bereitstellung ein für alle Mal auf Ihrem High-Memory-Server mit vielen Kern-Build-Servern kompiliert - Optimierungen vornehmen kann, die ein C # -kompiliertes Programm ermöglicht kann nicht, weil es eine Menge Zeit dafür hat. Der Compiler kann feststellen, ob es sich bei dem Computer um Intel oder AMD handelt. Pentium 4, Core Solo oder Core Duo; oder wenn SSE4 usw. unterstützt wird und Ihr Compiler den Laufzeitversand nicht unterstützt, können Sie dies selbst lösen, indem Sie eine Handvoll spezialisierter Binärdateien bereitstellen.
Das AC # -Programm wird normalerweise beim Ausführen so kompiliert, dass es auf allen Computern ordnungsgemäß ausgeführt wird. Es ist jedoch nicht so stark optimiert, wie es für eine einzelne Konfiguration (z. B. Prozessor, Befehlssatz, andere Hardware) möglich ist, und es muss einige Zeit in Anspruch nehmen zuerst. Funktionen wie Schleifenspaltung, Schleifeninversion, automatische Vektorisierung, Optimierung des gesamten Programms, Vorlagenerweiterung, Börsengang und vieles mehr sind nur schwer und vollständig auf eine Weise zu lösen, die den Endbenutzer nicht stört.
Zusätzlich ermöglichen bestimmte Sprachfunktionen dem Compiler in C ++ oder C, Annahmen über Ihren Code zu treffen, die es ihm ermöglichen, bestimmte Teile zu optimieren, die für den Java / C # -Compiler einfach nicht sicher sind. Wenn Sie keinen Zugriff auf die vollständige Typ-ID von Generika oder einen garantierten Programmablauf haben, gibt es viele Optimierungen, die einfach nicht sicher sind.
Außerdem führen C ++ und C viele Stapelzuweisungen gleichzeitig mit nur einer Registerinkrementierung durch, was sicherlich effizienter ist als die Zuordnungen von Javas und C # für die Abstraktionsebene zwischen dem Garbage Collector und Ihrem Code.
Jetzt kann ich in diesem nächsten Punkt nicht für Java sprechen, aber ich weiß, dass C ++ - Compiler beispielsweise tatsächlich Methoden und Methodenaufrufe entfernen, wenn sie wissen, dass der Hauptteil der Methode leer ist, häufige Unterausdrücke eliminieren und möglicherweise versuchen, es erneut zu versuchen Um eine optimale Registernutzung zu finden, erzwingt es keine Überprüfung der Grenzen, es automatisiert Schleifen und innere Schleifen automatisch und invertiert innere nach äußere, es verschiebt Bedingungen aus Schleifen heraus, es teilt und trennt Schleifen. Es wird std :: vector in native Null-Overhead-Arrays erweitern, wie Sie es auf C-Weise tun würden. Es werden interprozedurale Optimierungen durchgeführt. Es werden Rückgabewerte direkt am Aufruferstandort erstellt. Es wird Ausdrücke falten und verbreiten. Die Daten werden cachefreundlich neu angeordnet. Es wird Jump Threading machen. Sie können damit Raytracer zur Kompilierungszeit ohne Laufzeitaufwand schreiben. Es werden sehr teure graphbasierte Optimierungen vorgenommen. Es wird die Stärke reduzieren, wenn es bestimmte Codes durch syntaktisch völlig ungleichen, aber semantisch äquivalenten Code ersetzt (das alte "xor foo, foo" ist nur die einfachste, wenn auch veraltete Optimierung dieser Art). Wenn Sie es freundlich fragen, können Sie IEEE-Gleitkommastandards weglassen und noch mehr Optimierungen wie die Neuordnung von Gleitkommaoperanden aktivieren. Nachdem Ihr Code massiert und massakriert wurde, wird möglicherweise der gesamte Vorgang wiederholt, da häufig bestimmte Optimierungen die Grundlage für noch sicherere Optimierungen bilden. Es kann auch sein, dass Sie es erneut mit gemischten Parametern versuchen und sehen, wie die andere Variante in ihrem internen Ranking punktet. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden. Wenn es bestimmte Codes durch syntaktisch völlig ungleichen, aber semantisch äquivalenten Code ersetzt (das alte "xor foo, foo" ist nur die einfachste, wenn auch veraltete Optimierung dieser Art). Wenn Sie es freundlich fragen, können Sie IEEE-Gleitkommastandards weglassen und noch mehr Optimierungen wie die Neuordnung von Gleitkommaoperanden aktivieren. Nachdem Ihr Code massiert und massakriert wurde, wird möglicherweise der gesamte Vorgang wiederholt, da häufig bestimmte Optimierungen die Grundlage für noch sicherere Optimierungen bilden. Es kann auch sein, dass Sie es erneut mit gemischten Parametern versuchen und sehen, wie die andere Variante in ihrem internen Ranking punktet. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden. Wenn es bestimmte Codes durch syntaktisch völlig ungleichen, aber semantisch äquivalenten Code ersetzt (das alte "xor foo, foo" ist nur die einfachste, wenn auch veraltete Optimierung dieser Art). Wenn Sie es freundlich fragen, können Sie IEEE-Gleitkommastandards weglassen und noch mehr Optimierungen wie die Neuordnung von Gleitkommaoperanden aktivieren. Nachdem Ihr Code massiert und massakriert wurde, wird möglicherweise der gesamte Vorgang wiederholt, da häufig bestimmte Optimierungen die Grundlage für noch sicherere Optimierungen bilden. Es kann auch sein, dass Sie es erneut mit gemischten Parametern versuchen und sehen, wie die andere Variante in ihrem internen Ranking punktet. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden. Wenn Sie es freundlich fragen, können Sie IEEE-Gleitkommastandards weglassen und noch mehr Optimierungen wie die Neuordnung von Gleitkommaoperanden aktivieren. Nachdem Ihr Code massiert und massakriert wurde, wird möglicherweise der gesamte Vorgang wiederholt, da häufig bestimmte Optimierungen die Grundlage für noch sicherere Optimierungen bilden. Es kann auch sein, dass Sie es erneut mit gemischten Parametern versuchen und sehen, wie die andere Variante in ihrem internen Ranking punktet. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden. Wenn Sie es freundlich fragen, können Sie IEEE-Gleitkommastandards weglassen und noch mehr Optimierungen wie die Neuordnung von Gleitkommaoperanden aktivieren. Nachdem Ihr Code massiert und massakriert wurde, wird möglicherweise der gesamte Vorgang wiederholt, da häufig bestimmte Optimierungen die Grundlage für noch sicherere Optimierungen bilden. Es kann auch sein, dass Sie es erneut mit gemischten Parametern versuchen und sehen, wie die andere Variante in ihrem internen Ranking punktet. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden. Möglicherweise wird es auch nur mit gemischten Parametern wiederholt, um zu sehen, wie die andere Variante in ihrem internen Ranking punktet. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden. Möglicherweise wird es auch nur mit gemischten Parametern wiederholt, um zu sehen, wie die andere Variante in ihrem internen Ranking punktet. Und es wird diese Art von Logik in Ihrem gesamten Code verwenden.
Wie Sie sehen, gibt es viele Gründe, warum bestimmte C ++ - oder C-Implementierungen schneller sind.
Nachdem dies alles gesagt ist, können in C ++ viele Optimierungen vorgenommen werden, die alles wegblasen, was Sie mit C # tun können, insbesondere im Bereich der Zahlenkalkulation, Echtzeit und Metallnähe, aber nicht ausschließlich dort. Sie müssen nicht einmal einen einzigen Zeiger berühren, um einen langen Weg zurückzulegen.
Je nachdem, was Sie schreiben, würde ich mit dem einen oder anderen gehen. Aber wenn Sie etwas schreiben, das nicht hardwareabhängig ist (Treiber, Videospiel usw.), würde ich mir keine Sorgen um die Leistung von C # machen (ich kann wieder nicht über Java sprechen). Es wird gut gehen.
<<<<<<<<<<<
Im Allgemeinen klingen bestimmte verallgemeinerte Argumente in bestimmten Posts möglicherweise cool, klingen aber im Allgemeinen nicht mit Sicherheit glaubwürdig.
Wie auch immer, um Frieden zu schließen: AOT ist großartig, genau wie JIT . Die einzig richtige Antwort kann sein: Es kommt darauf an. Und die wirklich klugen Leute wissen, dass man sowieso das Beste aus beiden Welten nutzen kann.
quelle
Dies würde nur passieren, wenn der Java-Interpreter Maschinencode erzeugt, der tatsächlich besser optimiert ist als der Maschinencode, den Ihr Compiler für den von Ihnen geschriebenen C ++ - Code generiert, bis zu dem Punkt, an dem der C ++ - Code langsamer als Java ist und die Interpretationskosten.
Die Wahrscheinlichkeit, dass dies tatsächlich geschieht, ist jedoch ziemlich gering - es sei denn, Java verfügt möglicherweise über eine sehr gut geschriebene Bibliothek und Sie haben Ihre eigene schlecht geschriebene C ++ - Bibliothek.
quelle
Tatsächlich läuft C # nicht wirklich in einer virtuellen Maschine wie Java. IL wird in Assemblersprache kompiliert, die vollständig nativer Code ist und mit der gleichen Geschwindigkeit wie nativer Code ausgeführt wird. Sie können eine .NET-Anwendung vorab JITEN, wodurch die JIT-Kosten vollständig entfallen, und dann führen Sie vollständig nativen Code aus.
Die Verlangsamung mit .NET ist nicht darauf zurückzuführen, dass .NET-Code langsamer ist, sondern darauf, dass hinter den Kulissen viel mehr getan wird, um beispielsweise Müll zu sammeln, Referenzen zu überprüfen, vollständige Stapelrahmen zu speichern usw. Dies kann sehr leistungsfähig und hilfreich sein, wenn Erstellen von Anwendungen, aber auch mit Kosten verbunden. Beachten Sie, dass Sie all diese Dinge auch in einem C ++ - Programm ausführen können (ein Großteil der .NET-Kernfunktionalität besteht aus .NET-Code, den Sie in ROTOR anzeigen können). Wenn Sie jedoch dieselbe Funktionalität von Hand geschrieben haben, erhalten Sie wahrscheinlich ein viel langsameres Programm, da die .NET-Laufzeit optimiert und genau abgestimmt wurde.
Eine der Stärken von verwaltetem Code ist jedoch, dass er vollständig überprüfbar ist, d. H. Sie können überprüfen, ob der Code niemals auf den Speicher eines anderen Prozesses zugreift oder unsage Dinge ausführt, bevor Sie ihn ausführen. Microsoft hat einen Forschungsprototyp eines vollständig verwalteten Betriebssystems, der überraschenderweise gezeigt hat, dass eine zu 100% verwaltete Umgebung tatsächlich eine erheblich schnellere Leistung als jedes moderne Betriebssystem erbringen kann, indem diese Überprüfung genutzt wird, um Sicherheitsfunktionen zu deaktivieren, die von verwalteten Programmen nicht mehr benötigt werden (Wir sprechen in einigen Fällen wie 10x). SE Radio hat eine großartige Folge, die über dieses Projekt spricht.
quelle
In einigen Fällen kann verwalteter Code tatsächlich schneller sein als nativer Code. Beispielsweise ermöglichen "Mark-and-Sweep" -Garbage-Collection-Algorithmen Umgebungen wie JRE oder CLR, eine große Anzahl kurzlebiger (normalerweise) Objekte in einem einzigen Durchgang freizugeben, wobei die meisten C / C ++ - Heap-Objekte einzeln freigegeben werden. eine Zeit.
Aus Wikipedia :
Trotzdem habe ich viel C # und viel C ++ geschrieben und viele Benchmarks durchgeführt. Nach meiner Erfahrung ist C ++ viel schneller als C #, auf zwei Arten: (1) , wenn Sie einen Code nehmen , dass Sie in C # geschrieben haben, Portierung auf C ++ der nativen Code neigt dazu , schneller zu sein. Wie viel schneller? Nun, es ist sehr unterschiedlich, aber es ist nicht ungewöhnlich, dass sich die Geschwindigkeit um 100% verbessert. (2) In einigen Fällen kann die Speicherbereinigung eine verwaltete Anwendung massiv verlangsamen. Die .NET CLR leistet schreckliche Arbeit mit großen Haufen (z. B.> 2 GB) und kann viel Zeit in GC verbringen - selbst in Anwendungen, in denen nur wenige oder gar keine Objekte mit mittlerer Lebensdauer vorhanden sind.
Natürlich sind verwaltete Sprachen in den meisten Fällen, auf die ich gestoßen bin, bei weitem schnell genug, und der Kompromiss zwischen Wartung und Codierung für die zusätzliche Leistung von C ++ ist einfach nicht gut.
quelle
Hier ist ein interessanter Benchmark http://zi.fi/shootout/
quelle
Tatsächlich verwendet die HotSpot-JVM von Sun die Ausführung im gemischten Modus. Es interpretiert den Bytecode der Methode, bis es (normalerweise durch einen Zähler) feststellt, dass ein bestimmter Codeblock (Methode, Schleife, Try-Catch-Block usw.) häufig ausgeführt wird, und kompiliert ihn dann von JIT. Die zum JIT-Kompilieren einer Methode erforderliche Zeit dauert häufig länger als bei einer Interpretation der Methode, wenn es sich um eine selten ausgeführte Methode handelt. Die Leistung ist im "gemischten Modus" normalerweise höher, da die JVM keine Zeit mit JITing-Code verschwendet, der selten, wenn überhaupt, ausgeführt wird. C # und .NET tun dies nicht. .NET JITs alles, was oftmals Zeit verschwendet.
quelle
Lesen Sie mehr über Dynamo von HP Labs , einen Interpreter für PA-8000, der auf PA-8000 ausgeführt wird und Programme häufig schneller ausführt als nativ. Dann scheint es überhaupt nicht überraschend!
Betrachten Sie es nicht als "Zwischenschritt" - das Ausführen eines Programms umfasst bereits viele andere Schritte in jeder Sprache.
Es kommt oft darauf an:
Programme haben Hotspots. Selbst wenn Sie 95% des auszuführenden Codes langsamer ausführen, können Sie dennoch wettbewerbsfähig sein, wenn Sie bei den heißen 5% schneller sind.
Eine HLL weiß mehr über Ihre Absicht als eine LLL wie C / C ++ und kann daher optimierten Code generieren (OCaml hat noch mehr und ist in der Praxis oft sogar noch schneller).
Ein JIT-Compiler verfügt über viele Informationen, die ein statischer Compiler nicht hat (wie die tatsächlichen Daten, die Sie diesmal haben).
Ein JIT-Compiler kann zur Laufzeit Optimierungen vornehmen, die herkömmliche Linker nicht wirklich ausführen dürfen (z. B. das Neuordnen von Zweigen, sodass der allgemeine Fall flach ist, oder das Inlining von Bibliotheksaufrufen).
Alles in allem sind C / C ++ für die Leistung ziemlich miese Sprachen: Es gibt relativ wenig Informationen zu Ihren Datentypen, keine Informationen zu Ihren Daten und keine dynamische Laufzeit, um die Laufzeitoptimierung zu verbessern.
quelle
Es kann zu kurzen Bursts kommen, wenn Java oder CLR schneller als C ++ sind, aber insgesamt ist die Leistung für die Lebensdauer der Anwendung schlechter: Einige Ergebnisse hierzu finden Sie unter www.codeproject.com/KB/dotnet/RuntimePerformance.aspx.
quelle
Hier ist die Antwort von Cliff Click: http://www.azulsystems.com/blog/cliff/2009-09-06-java-vs-c-performanceagain
quelle
Das ist unlogisch. Die Verwendung einer Zwischendarstellung beeinträchtigt die Leistung nicht von Natur aus. Zum Beispiel kompiliert llvm-gcc C und C ++ über LLVM IR (eine virtuelle Maschine mit unendlichen Registern) zu nativem Code und erzielt eine hervorragende Leistung (oft besser als GCC).
Hier sind einige Beispiele:
Virtuelle Maschinen mit JIT-Kompilierung erleichtern die Generierung von Laufzeitcode (z. B.
System.Reflection.Emit
in .NET), sodass Sie generierten Code im laufenden Betrieb in Sprachen wie C # und F # kompilieren können, müssen jedoch einen vergleichsweise langsamen Interpreter in C oder C ++ schreiben. Zum Beispiel, um reguläre Ausdrücke zu implementieren.Teile der virtuellen Maschine (z. B. die Schreibbarriere und der Allokator) werden häufig in handcodierten Assemblern geschrieben, da C und C ++ nicht schnell genug Code generieren. Wenn ein Programm diese Teile eines Systems betont, kann es möglicherweise alles übertreffen, was in C oder C ++ geschrieben werden kann.
Die dynamische Verknüpfung von nativem Code erfordert die Konformität mit einem ABI, der die Leistung beeinträchtigen und die Optimierung des gesamten Programms verhindern kann, während die Verknüpfung normalerweise auf VMs verzögert wird und von Optimierungen des gesamten Programms (wie den reifizierten Generika von .NET) profitieren kann.
Ich möchte auch einige Probleme mit der oben hoch bewerteten Antwort von paercebal ansprechen (weil immer wieder jemand meine Kommentare zu seiner Antwort löscht), die eine kontraproduktiv polarisierte Sichtweise darstellen:
Daher funktioniert die Metaprogrammierung von Vorlagen nur, wenn das Programm zur Kompilierungszeit verfügbar ist, was häufig nicht der Fall ist, z. B. ist es unmöglich, eine wettbewerbsfähig performante Bibliothek für reguläre Ausdrücke in Vanilla C ++ zu schreiben, da sie nicht in der Lage ist, Laufzeitcode zu generieren (ein wichtiger Aspekt von Metaprogrammierung).
In C # gilt dies nur für Referenztypen und nicht für Werttypen.
Die Leute haben beobachtet, dass Java beim SOR-Test aus dem SciMark2-Benchmark C ++ schlägt, gerade weil Zeiger aliasingbezogene Optimierungen behindern.
Erwähnenswert ist auch, dass .NET nach dem Verknüpfen eine Typenspezialisierung von Generika für dynamisch verknüpfte Bibliotheken durchführt, während dies in C ++ nicht möglich ist, da Vorlagen vor dem Verknüpfen aufgelöst werden müssen. Und der große Vorteil von Generika gegenüber Vorlagen sind natürlich verständliche Fehlermeldungen.
quelle
Zusätzlich zu dem, was einige andere gesagt haben, sind .NET und Java meines Wissens besser in der Speicherzuweisung. Zum Beispiel können sie Speicher komprimieren, wenn er fragmentiert wird, während C ++ dies nicht kann (nativ, aber es kann, wenn Sie einen cleveren Garbage Collector verwenden).
quelle
Für alles, was viel Geschwindigkeit benötigt, ruft die JVM nur eine C ++ - Implementierung auf. Es geht also eher darum, wie gut ihre Bibliotheken sind, als darum, wie gut die JVM für die meisten betriebssystembezogenen Dinge ist. Die Speicherbereinigung halbiert Ihren Speicher, aber die Verwendung einiger der schickeren STL- und Boost-Funktionen hat den gleichen Effekt, jedoch mit einem vielfachen Fehlerpotential.
Wenn Sie in einem großen Projekt mit vielen Klassen nur C ++ - Bibliotheken und viele der Funktionen auf hoher Ebene verwenden, werden Sie wahrscheinlich langsamer als mit einer JVM. Außer viel fehleranfälliger.
Der Vorteil von C ++ ist jedoch, dass Sie sich selbst optimieren können, da Sie sonst nicht mehr mit dem arbeiten können, was der Compiler / jvm tut. Wenn Sie Ihre eigenen Container erstellen, Ihre eigene Speicherverwaltung schreiben, die ausgerichtet ist, SIMD verwenden und hier und da zur Assembly wechseln, können Sie mindestens das 2- bis 4-fache der Leistung der meisten C ++ - Compiler selbst beschleunigen. Für einige Operationen 16x-32x. Das bedeutet, dass dieselben Algorithmen verwendet werden. Wenn Sie bessere Algorithmen verwenden und parallelisieren, können die Erhöhungen dramatisch sein, manchmal tausende Male schneller als bei häufig verwendeten Methoden.
quelle
Ich betrachte es aus verschiedenen Blickwinkeln.
quelle
Eine sehr kurze Antwort: Mit einem festen Budget erzielen Sie eine leistungsstärkere Java-Anwendung als eine C ++ - Anwendung (ROI-Überlegungen). Darüber hinaus verfügt die Java-Plattform über anständigere Profiler, mit denen Sie Ihre Hotspots schneller lokalisieren können
quelle