Ich bin ein C ++ - und ein C # -Entwickler. Ich habe seit der ersten Beta des .NET Frameworks C # -Anwendungen entwickelt und mehr als 20 Jahre Erfahrung in der Entwicklung von C ++ - Anwendungen. Erstens wird C # -Code NIEMALS schneller sein als eine C ++ - Anwendung, aber ich werde nicht lange auf verwalteten Code, seine Funktionsweise, die Inter-Op-Schicht, interne Speicherverwaltungsschichten, das dynamische Typsystem und den Garbage Collector eingehen. Lassen Sie mich dennoch weiter sagen, dass die hier aufgeführten Benchmarks alle zu FALSCHEN Ergebnissen führen.
Lassen Sie mich erklären: Das erste, was wir berücksichtigen müssen, ist der JIT-Compiler für C # (.NET Framework 4). Jetzt erzeugt die JIT nativen Code für die CPU unter Verwendung verschiedener Optimierungsalgorithmen (die tendenziell aggressiver sind als das mit Visual Studio gelieferte Standard-C ++ - Optimierungsprogramm), und der vom .NET JIT-Compiler verwendete Befehlssatz spiegelt die tatsächliche CPU genauer wider Auf der Maschine könnten bestimmte Ersetzungen im Maschinencode vorgenommen werden, um Taktzyklen zu reduzieren und die Trefferquote im CPU-Pipeline-Cache zu verbessern und weitere Hyper-Threading-Optimierungen wie die Neuordnung von Befehlen und Verbesserungen in Bezug auf die Verzweigungsvorhersage zu erzielen.
Dies bedeutet, dass Ihre C ++ - Anwendung möglicherweise langsamer als die entsprechende C # - oder .NET-basierte Anwendung ausgeführt wird, wenn Sie Ihre C ++ - Anwendung nicht mit den richtigen Pararmetern für den RELEASE-Build kompilieren (nicht für den DEBUG-Build). Stellen Sie beim Angeben der Projekteigenschaften in Ihrer C ++ - Anwendung sicher, dass Sie "vollständige Optimierung" und "schnellen Code bevorzugen" aktivieren. Wenn Sie einen 64-Bit-Computer haben, MÜSSEN Sie angeben, dass x64 als Zielplattform generiert werden soll. Andernfalls wird Ihr Code über eine Konvertierungsunterschicht (WOW64) ausgeführt, wodurch die Leistung erheblich verringert wird.
Sobald Sie die richtigen Optimierungen im Compiler durchgeführt haben, erhalte ich 0,72 Sekunden für die C ++ - Anwendung und 1,16 Sekunden für die C # -Anwendung (beide im Release-Build). Da die C # -Anwendung sehr einfach ist und den in der Schleife verwendeten Speicher auf dem Stapel und nicht auf dem Heap zuweist, ist sie tatsächlich viel leistungsfähiger als eine echte Anwendung, die an Objekten, umfangreichen Berechnungen und größeren Datenmengen beteiligt ist. Die angegebenen Zahlen sind also optimistische Zahlen, die auf C # und das .NET-Framework ausgerichtet sind. Trotz dieser Tendenz ist die C ++ - Anwendung in etwas mehr als der Hälfte der Zeit fertig als die entsprechende C # -Anwendung. Beachten Sie, dass der von mir verwendete Microsoft C ++ - Compiler nicht über die richtige Pipeline- und Hyperthreading-Optimierung verfügte (Verwenden von WinDBG zum Anzeigen der Montageanweisungen).
Wenn wir nun den Intel-Compiler verwenden (der übrigens ein Branchengeheimnis für die Generierung von Hochleistungsanwendungen auf AMD / Intel-Prozessoren ist), wird derselbe Code für die ausführbare C ++ - Datei in 0,54 Sekunden ausgeführt, für Microsoft Visual Studio 2010 in 0,72 Sekunden Am Ende sind die Endergebnisse für C ++ 0,44 Sekunden und für C # 1,16 Sekunden. Der vom .NET JIT-Compiler erzeugte Code dauert also 214% länger als die ausführbare C ++ - Datei. Die meiste Zeit in den .54 Sekunden wurde damit verbracht, die Zeit vom System zu erhalten und nicht innerhalb der Schleife selbst!
Was in der Statistik ebenfalls fehlt, sind die Start- und Bereinigungszeiten, die nicht in den Timings enthalten sind. C # -Anwendungen verbringen in der Regel viel mehr Zeit mit dem Starten und Beenden als C ++ - Anwendungen. Der Grund dafür ist kompliziert und hängt mit den Validierungsroutinen für den .NET-Laufzeitcode und dem Speicherverwaltungssubsystem zusammen, das zu Beginn (und folglich am Ende) des Programms viel Arbeit leistet, um die Speicherzuordnungen und den Müll zu optimieren Kollektor.
Bei der Messung der Leistung von C ++ und .NET IL ist es wichtig, den Assemblycode zu überprüfen, um sicherzustellen, dass ALLE Berechnungen vorhanden sind. Was ich gefunden habe, ist, dass ohne zusätzlichen Code in C # der größte Teil des Codes in den obigen Beispielen tatsächlich aus der Binärdatei entfernt wurde. Dies war auch bei C ++ der Fall, als Sie einen aggressiveren Optimierer wie den mit dem Intel C ++ - Compiler gelieferten verwendeten. Die Ergebnisse, die ich oben angegeben habe, sind zu 100% korrekt und werden auf Baugruppenebene validiert.
Das Hauptproblem bei vielen Foren im Internet ist, dass viele Neulinge Microsoft-Marketingpropaganda hören, ohne die Technologie zu verstehen, und falsche Behauptungen aufstellen, dass C # schneller als C ++ ist. Die Behauptung ist, dass C # theoretisch schneller als C ++ ist, weil der JIT-Compiler den Code für die CPU optimieren kann. Das Problem bei dieser Theorie ist, dass im .NET Framework viele Installationen vorhanden sind, die die Leistung verlangsamen. Sanitär, das in C ++ - Anwendung nicht vorhanden ist. Darüber hinaus kennt ein erfahrener Entwickler den richtigen Compiler für die jeweilige Plattform und verwendet beim Kompilieren der Anwendung die entsprechenden Flags. Auf Linux- oder Open Source-Plattformen ist dies kein Problem, da Sie Ihre Quelle verteilen und Installationsskripte erstellen können, die den Code mithilfe der entsprechenden Optimierung kompilieren. Auf Windows- oder Closed Source-Plattformen müssen Sie mehrere ausführbare Dateien mit jeweils spezifischen Optimierungen verteilen. Die Windows-Binärdateien, die bereitgestellt werden, basieren auf der vom MSI-Installationsprogramm erkannten CPU (mithilfe benutzerdefinierter Aktionen).