Die Community zu .NET und Classic VB.
Menü

Warum ist C++ denn nun so schnell?

 von 

Übersicht 

C++ wird generell als eine sehr effiziente Sprache gehandelt, wann immer ein Code in VB nicht schnell genug läuft, schallt von allen Seiten der Ruf „schreib’s in C++“. – Allerdings scheint den meisten nicht bewusst zu sein, woher diese Geschwindigkeit denn nun kommt. Dieser Artikel versucht zu erklären, wieso C++ (und nicht etwa C) tatsächlich eine schnelle Sprache ist.

Mit freundlichen Grüßen,
Konrad Ludwig Moritz Rudolph

Motivation  

Nun, ist C++ denn überhaupt schneller als andere Programmiersprachen (speziell VB)? Kurz und knapp: ja. Für vergleichbare Programme gilt das in fast allen (ich schätze mal, >> 90%) Fällen. Signifikant ist der Unterschied allerdings in sehr viel weniger Fällen. Ich werde diesen Geschwindigkeitsunterschied im folgenden auf eine technische Basis stellen, aber zuerst werde ich darauf eingehen, aus welchen Gründen C++ nicht schneller ist:

Falsche Voraussetzungen  

Oft wird angeführt, der Geschwindigkeitsvorteil läge daran, dass C++ systemnäher sei. Das ist Quatsch. Systemnähe ist kein a-priori-Grund für größere Geschwindigkeit. Moderne Compiler sind in der Lage, die „Verpackung“ von allgemeiner Abstraktion (durch Prozeduren, Modularisierung, Objektorientierung und teilweise auch Funktionalisierung) erstaunlich gut aus dem Weg zu räumen. Sicher, C++ kennt das Schlüsselwort register, das angibt, dass eine lokale Variable möglichst in einem CPU-Register abgelegt werden soll – aber anscheinend beachtet das kaum noch ein moderner C++-Compiler. Der Compiler kann viel besser als der Programmierer entscheiden, welche Variablen er in CPU-Registern ablegt, dafür bedarf es keines Schlüsselworts. Ähnliches gilt für das Schlüsselwort inline. Diese Empfehlung an den Compiler kann man sich ebenfalls getrost schenken, es sei denn, man hat aufwendige Profiling-Tests durchgeführt, die der Compiler evtl. in dieser Form nicht selbst ausführen kann, und hat so herausgefunden, dass der Funktionsaufruf einer großen Methode ein Flaschenhals ist – dieser Fall ist aber extrem selten.

Ein anderer vollkommen falscher Grund ist die Behauptung, das läge daran, dass C++ eine spezielle Syntax für den Zugriff auf Zeiger habe. Wieso sollte das die Geschwindigkeit erhöhen? Zugegeben, Referenzzählung kann relativ langsam sein. Aber .NET hat keinen Referenzzähler. Die Speicherverwaltung in .NET ist – bis auf seltene Intervalle – unschlagbar schnell.

Also, woran kann es denn nun liegen?

Tatsächliche Gründe  

  • C++ existiert seit 1985 und basiert auf dem noch älteren C. Im Gegensatz zu z.B. VB wurden Compiler ständig erweitert und mit dem Wissen älterer Modelle erneuert. Aufgrund der industriellen Verbreitung von C/C++ lag teilweise ein enormer Druck auf den Compilerbauern (die oft dieselben wie die Anwender von C++ waren), die Geschwindigkeit zu verbessern. C++ ist daher heutzutage einer der Compiler, in die am meisten Know-How geflossen ist und die am besten optimieren, geschlagen vielleicht nur von Fortran- und Scheme-Compilern. (Hier kann man mir leicht einen Strick draus drehen. Viele andere Compiler und Interpreter optimieren sehr gut, vor allem auch Smalltalk. Aber es bleibt meistens dabei, dass im Endeffekt in Reallife-Anwendungen das C++-Resultat das schnellste ist.)

  • C++ ist eine strikt standardisierte Sprache. Diese Standardisierung erlaubt teilweise rigorose Annahmen über die Semantik des Codes, die ausgenutzt werden können, um überflüssige Aufrufe wegzuoptimieren. C++’ Syntax ist zudem dermaßen dynamisch, dass viele der Tricks, die heute zum guten Ton in C++ gehören, erst nachträglich entdeckt wurden und ständig verbessert wurden. Dadurch wurden eine Menge trickreicher Mechanismen hervorgebracht, die Sprachmerkmale für die Optimierung ausnutzen.

  • Das Schlüsselwort const. const ist sehr viel weitreichender als final in Java und ReadOnly in VB/C#. Durch const-correctness sind extrem rabiate Optimierungen möglich, da der Compiler sichergehen kann, dass gewisse Schreib-Operationen nie auftreten können. Tun sie es doch (was nur durch ein explizites const_cast geht, was gewissermaßen ein rotes Warnsignal im Code ist), ist der Programmierer schuld und das Programm geht spektakulär flöten.

  • C++-Compiler inlinen sehr gut. Ich habe bereits erwähnt, dass C++-Compiler gut optimieren, aber das Inlining muss hier speziell hervorgehoben werden, denn das machen C++-Compiler so gut, dass äquivalente Codes in C++ schneller sein können als in C, allein aus dem Grund, dass der C++-Compiler indirekte Aufrufe inlinen kann, die in C++ als Funktoren implementiert sind und in C als Funktionszeiger.

  • Das geht natürlich nur wegen der Operatorenüberladung des ()-Operators in C++, der Klassen erlaubt, die sich wie Funktionszeiger verhalten, all deren Vorteile, aber nicht deren Nachteile (Indirektion und damit Geschwindigkeitsverlust) haben.

  • C++ ist nicht vollständig objektorientiert im klassischen Smalltalk-Sinn (sehr wohl aber in dem Sinn, dass in der STL alles über Objekte ausgedrückt wird). OO an sich ist oft sehr langsam, da virtuelle Methodenaufrufe und Referenzobjekte verwendet werden müssen, um OO-Techniken wie Laufzeitpolymorphismus zu verwenden. Daran führt kein Weg vorbei, auch in C++ nicht, aber C++ verwendet nur in kleinen Teilen OO. Meistens erstellt man auch keine Zeiger auf Objekte, sondern konkrete Objekte. Laufzeit-Polymorphismus wird durch die Templates in sehr vielen Fällen in Compilezeit-Polymorphismus umgewandelt. Das ganze geht so weit, dass ich persönlich in C++ kaum mit Zeigern arbeite. Ich kenne an der Uni viele Programmierer, die das nicht glauben wollen (na ja, das sind C-Leute aus der Unix-Welt …), aber viele hochkarätige C++-Programmierer machen es vor.

  • Die Templates. .NET besitzt Generics, aber C++’ Templates sind einfach viel schneller. Das hat verschiedene technische Gründe und dadurch entstehen nicht nur Vorteile: Die Templates sind der Grund dafür, dass es keine guten C++-IDEs gibt: Für guten IntelliSense und gutes Refactoring muss der Code im Hintergrund kompiliert und analysiert werden und das ist mit Templates einfach nicht machbar, weil die Auswertung hier einfach zu langsam ist. Aber auf der Plus-Seite bedeuten Templates, dass man Code auf einer sehr hohen Abstraktionsebene schreiben kann, der Compiler diesen Code aber vollautomatisch in Low-Level-Befehle verwandelt, die nicht einmal mehr großer Optimierung bedürfen, da sie bereits konkretisiert sind.

  • Die Standard-Bibliothek. Ich habe sie in meiner Aufzählung bis zum Schluss gelassen, aber die STL (und die Boost-Bibliothek) ist wohl der Hauptgrund dafür, dass C++ im (relevanten) Normalfall schneller (oder zumindest bei gleicher Geschwindigkeit wesentlich weniger komplex) ist als C – und damit wohl schneller als alle existierenden Hochsprachen. Die STL wurde mit dem Augenmerk „Effizienz“ (mit gleichzeitiger extrem hoher Wiederverwendbarkeit) designed. Das allein unterschiedet sie von den meisten Bibliotheken. In .NET z.B. wurden viele Klassen extrem effizient implementiert (die List-Klasse z.B. ist mit eigenem Code nicht zu schlagen!) – aber es fehlt ein schlüssiges Gesamtkonzept. In .NET sind viele Klassen für sich genommen schnell, aber sobald man Daten von einem Algorithmus in den nächsten überführt, entstehen Flaschenhälse, die der Compiler nicht weg-optimieren kann. In C++ ist das Gegenteil der Fall. Hier wurde auf eine enge Verzahnung der verschiedenen Klassen geachtet, die es erlaubt, Werte ohne Flaschenhälse von einem logischen Schritt in den nächsten zu überführen. Und selbst diese Überführung kann häufig vollkommen weg-optimiert werden.

Praxisbelege  

Belege für Überlegenheit in praktischen Anwendungen zu finden ist immer schwer, da es nicht trivial ist, solche Anwendungen im Bezug auf Komplexität und Effizienz fair zu vergleichen. Gezielt Beispielcodes zu schreiben und dann zu vergleichen ist gleichfalls schwer, da solche Codes selten praxisrelevant sind. Die Computer Language Shootout Benchmarks haben genau mit solchen Problemen zu kämpfen, ich würde daher nicht empfehlen, diese Beispiele als gute Referenz zu akzeptieren. Mit gesunder Skepsis kann man trotzdem mal einen Blick auf die Ergebnisse wagen.

Tatsächlich zeigt sich, dass sehr unterschiedliche Sprachen die jeweiligen Testergebnisse anführen, sich C und C++ aber fast immer im vorderen Feld befinden. Wenn man seinen Vergleich auf C und C++ beschränkt, erscheint das Ergebnis zuerst sehr ausgeglichen. Tatsächlich handelt es sich bei Codes, in denen C gewinnt, sowie solchen, in denen die Codes nahezu gleichschnell sind, um Fälle, welche nach einem absolut gleichen Algorithmus ein rein akademisches Problem lösen (mit einer Ausnahme – „cheap concurrency“: Offensichtlich besitzt C eine bessere Bibliothek für Multithreading als C++). Schaut man sich hingegen lediglich die praxisrelevanten Codes an und beachtet zusätzlich auch alternative C++-Lösungen, welche andere Algorithmen verwenden, so ist C++ haushoch überlegen.

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 31 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Grauberger am 17.01.2008 um 14:06

Ich finde diesen Artikel sehr Sachlich und vor allem gefällt mir das hier auf Fakten aufgebaut wird und das hier nicht ein Artikel ist der mit dem leidigen Thema der "besten Programmiersprache" ist. (nur für Kritiker ist Programmiere in Delphi!)

Weiter so!

Gruß
Grauberger

Kommentar von Klaus-Dieter Wittke am 28.10.2007 um 20:07

Betrift Antwort von Konrad L.M.Rudolph

Hallo,
da ich der Meinung war das V2.0 Projekte langsamer laufen wollte ich natürlich die Ursache für meine Meinung finden.
Folgendes:
in meinem Programm läuft ein separater Thread den ich allerdings innerhalb einer Do Loop Schleife nicht durch die Anweisung Thread.Sleep(0) unterbrochen hatte. Dies machte bei der Version 1.1 nicht merklich was aus, sehr wohl aber in der 2.0 Version.
nach einfügen der Anweisung konnte ich subjektiv gesehen keinen Geschwindigkeitsunterschied mehr feststellen.

Gruß
Klaus-Dieter

Kommentar von Nicem am 05.10.2007 um 20:37

Konrad,
Sorry für meine Voreingenommenheit, ich hab den Artikel nur überflogen.. eigentlich gehst du ja die Sache ziemlich sachlich und wirklich nur die Konzepte an. Wollte nich so übertrieben reagieren aber ich weis halt wer sich selbst zu helfen weiss kann mit VB auch alles erreichen.. und sei es mit raw bytes ausm Assembler raushauen und seine eigenen optimierten routinen zusammenbasteln. Wer weis wies geht. Dem steht die möglichkeit genauso offen superb schnelle applikationen zu schreiben. Das ist das was ich eigentlich sagen wollte. VB ist zwar RAD und ein "Baukasten" jedoch mit der Mögichkeit es bis biegen und brechen zu verdrehen und so dieses vorgefertigte zu umgehen. Wenn man das wissen dazu hat. Im prinzip sind die möglichkeiten bis unendlich und so kann man ALLES erreichen.. allerdings mit viel mühe.. und alles selbst zusammenbasteln. naja auch egal alles wollte niemand angreifen sorry

MFG Nicem

Kommentar von Konrad L. M. Rudolph am 05.10.2007 um 10:45

Nicem,

Du hast scheinbar den Kern dessen, was ich geschrieben habe, nicht verstanden (oder gar nicht gelesen? Es scheint so).

Mir ist schon bewusst, dass man auch in VB WinAPI verwenden kann und dadurch ein Arsenal effizienter Funktionen an der Hand hat. Das sind aber alles Micro-Optimierungen, und um die ging es in dem Artikel eben *nicht*. Stattdessen ging es darum, dass C++ vollkommen andere Konzepte der Programmierung erlaubt und unterstützt, als es dies VB tut. Und aufgrund dieser Konzepte kann man wesentlich effizienteren Code schreiben.

Dass der VB-Compiler Maschinencode genausogut optimiert wie ein C++-Compiler ist übrigens einfach nur falsch, das lässt sich auch sehr leicht nachprüfen.

Zu den von Dir erwähnten 1.000 Zeilen C++-Code: Das ist nicht viel. 100.000 Zeilen Code sind viel. Und genau hier zeigt sich auch ein Problem: Du hast zwar recht, dass man in C++ für einige Sachen 1000 Zeilen Code braucht, die man in VB in 10 Zeilen Code schreiben kann (ungefähr). Leider wird dieses Verhältnis bei größeren Projekten *nicht* gewahrt! Das heißt, ein C++-Projekt mit 100.000 Zeilen Code würde in VB ebenfalls (mindestens!) 100.000 Codezeilen brauchen! Das heißt in solchen Größenordnungen ist der Vorteil von VB nicht mehr vorhanden.

An Klaus-Dieter: Das kann ich mir nicht vorstellen. Das .NET-Framework 2.0 ist zwar im Vergleich zur ersten Version stark gewachsen, intern wurde aber extrem optimiert. Meine persönliche Erfahrung ist, dass .NET 2.0-Projekte viel schneller laufen als Projekte unter .NET 1.1.

Kommentar von Nicem am 04.10.2007 um 22:46

Völliger Schwachsinn, sicher die VB RAD IDE mit hier mal dialog da mal objekt.. typ variant... mid() instr() statt mid$() instr$() ... fehlendes wissen über befehlte wie noin() und blabla .. klar dann mag das alles langsamer sein nur es gibt immer noch Sub Main() -> und von hier aus kann man ALLES selbst schreiben. API etc. GENAUSO wie C++.. Der VB Compiler optimiert seinen machine-code (schleifen, ausdrücke, usw..) genauso gut wie ein C++ Compiler das problem ist nur es wird der vorgefertigte bullshit benutzt der übelst ablahmt.. is doch klar das jemand der von vornherein VB als babysprache sieht kein plan davon hat und abstempelt.. ich benutze VB seit ewigen jahren hab noch nie ein C++ projekt gesehen das besser und schneller war.. sah höchstens schlechter aus UND VB is 10 mal effizienter in der umsetzung von projekten. Schau dir mal C++ projekte an.. übelst kryptisch und 1000 c++ zeilen sind viell 10 vb zeilen.. es is einfach nur das wissen.. wie man VB benutzt genauso wie du scheiss lahmen code in c++ schreiben kannst und das muss man sich vor augen halten.

MFG Nicem

Kommentar von Klaus-Dieter am 27.08.2007 um 22:33

Hallo,
von C++ habe ich leider keine Ahnung.
Programmiere seit längerem mit VB.Net basierend auf framework 1.1
Von Microsoft gibt es eine kostenlose Express-Version mit framework 2.0. Habe festgestellt das die Programme damit viel langsamer laufen. Hat jemand ähnliche Erfahrungen, oder kann mir das erklären ?

Gruß
Klaus-Dieter

Kommentar von Konrad L. M. Rudolph am 08.04.2007 um 15:13

Hallo,

> Ich kann nicht zustimmen, da ich einige Test`s
> durchgefürt habeum festzustellen welche Sprache
> nun die schnellste ist (VB6 und VC6) z.b. net

Und bei diesem Test hast Du einige Fehler gemacht. Erst einmal hast Du nicht zwei Sprachen verglichen sondern zwei Compiler. Das ist ein riesiger Unterschied. Der VC6-Compiler ist bekanntermaßen schlecht und außerdem vollkommen veraltet. Es gibt inzwischen viel bessere Compiler.

> die immer zum selben Ergebnis führt die Überlegenheit
> ist ziemlich übertrieben.

Nein, Dein Test ist einfach ungeeignet:

> z.b. ein CPU Belastungsprogramm zählt wie viele
> Operationen es pro Durchlauf ausführen kann.

Ja, na ganz toll. Du zählst also, wieviele Operationen der Prozessor durchführen kann. Ja, schön. Da ist doch aber auch klar, dass unterschiedliche Sprachen gleiche Ergebnisse erbringen: Du misst hier im Prinzip *Prozessorleistung*!

> Da es keinen großen unterschied gibt sollte jeder
> Programmierer für sich entscheiden
> mit welcher Programmiersprache er umgehen will.

Lies Dir bitte nochmal meine Kolumne durch. Du scheinst überhaupt nicht verstanden zu haben, *was* C++ schneller macht bzw. *wo* C++ schneller ist als VB.

> Nur weil einige Professoren der Meinung sind VB
> währe eine Baby Sprache muss man nicht so eine
> Hetze veranstalten.

Wieso sollte ich ausgerechnet auf einer VB-Seite eine Anti-VB-Hetze veranstalten? Das ist nicht sinnvoll, oder? Hier wird keine Hetze veranstaltet. Es geht nur darum hinzuweisen, dass VB für einige Dinge eben nicht so gut geeignet ist wie andere Sprachen.

> Besonders weil VB6 und vc6 mit dem selben Compiler
> arbeiten

Das ist einfach falsch. VB6 und VC6 arbeiten natürlich *nicht* mit demselben Compiler. Ich würde zu gerne mal wissen, wer diesen Mythos in die Welt gesetzt hat. Das einzige, was VB6 und VC6 gemeinsam haben, ist der Linker.

> ansonsten bedeutet es nicht um so älter ein Compiler
> des to besser

Nein, das hat auch niemand behauptet. Es ging lediglich um die Ansammlung von Know-How. In die Compiler-Entwicklung von C++-Compilern ist über die Jahrzehnte ein enormes Know-How geflossen, das Compilerbau-Teams von anderen Sprachen nicht unbedingt zur Verfügung steht.

lg,
Konrad.

Kommentar von mgalpha am 08.04.2007 um 14:17

Ich kann nicht zustimmen, da ich einige Test`s durchgefürt habeum festzustellen welche Sprache nun die schnellste ist (VB6 und VC6) z.b. net

die immer zum selben Ergebnis führt die Überlegenheit ist ziemlich übertrieben.

Theoretisch mag das sein aber praktisch ist das eben nicht so.

z.b. ein CPU Belastungsprogramm zählt wie viele Operationen es pro Durchlauf ausführen kann.
Dabei wurde drauf geachtet das die Voraussetzungen annähert gleich sind für C++ und VB.


Erster Durchlauf
vb : 660012312

c++: 660012286
--------------------


vb : 660011890

c++: 660012026


die Unterschiede sind auf Belastungen anderer Programme zurückzuführen.

Da es keinen großen unterschied gibt sollte jeder Programmierer für sich entscheiden
mit welcher Programmiersprache er umgehen will. Nur weil einige Professoren
der Meinung sind VB währe eine Baby Sprache muss man nicht so eine Hetze veranstalten.


Besonders weil VB6 und vc6 mit dem selben Compiler arbeiten

ansonsten bedeutet es nicht um so älter ein Compiler des to besser

Schaut euch doch einfach Windows an !

Um so höher die Versionen werden desto großer wird der mist.
Und wieso weil jeder nur zeilen dazu fügt.

Dato wird alles größer und aufgeblasener.

das bedeutet aber nicht das es besser wird. Siehe win 95 , 98 ,win me, win nt, win 2000, win xp

wo win xp noch einen giga hatte, braucht win Vista schon 4 GB.

Manchmal ist es besser von vorne an zu fangen.

Mit freundlichen Grüßen

MGalpha

Kommentar von Stefan Unterreitmeier am 15.02.2007 um 18:31

Hallo Uwe,

danke für den Artikel! :)

Ihr seid zwar scheinbar über "inline" schon hinweg, aber mir schien, dass hier nur der theoretische Aspekt diskutiert wird, dass Klassen und ihre "kleinen" Zugriffsmethoden alle in einem Projekt verwendet werden => nur eine einzige Exec in einem Linkerlauf.

Schreibe ich aber eine Bibliothek für andere oder wächst das Projekt, muss ich anfangen den Code in den Header zu verschieben damit dieser Code in anderen Compilerläufen noch ge-inline-t werden kann. Dazu gibt es nur die Möglichkeiten die Methoden inline zu setzten, da der Linker sie sonst als gleichnamiges Symbol in mehreren Objects finden würde.

Diese inline setzen der Methoden kann einmal explizit ausserhalb der Klassendeklaration erfolgen, wofür das Schlüsselwort "inline" notwendig ist. Oder es kann implizit erfolgen, in dem man die Methode direkt in der Klassendeklaration definiert (was die Methode aber nicht weniger "inline" setzt).

Der Compiler kann zwar das inline immer noch ignorieren, das Schlüsselwort selbst ist im expliziten Fall aber zwingend erforderlich.

lg,
Stefan

Kommentar von Konrad L. M. Rudolph am 13.02.2007 um 10:52

Hallo Uwe,

nein, das hat mit der Geschwindigkeit zwar auch zu tun, liegt aber im Grunde daran, dass C++ und C besser als andere Sprachen das zugrundeliegende Hardwaremodell beschreiben und so oft eine direkte 1:1-Entsprechung der Hardware im Code repräsentieren können. Das liegt vor allem an der Einführung von Zeigern in C (Zeiger waren vorher in Programmiersprachen nicht selbstverständlich).

Dass hier hauptsächlich C verwendet wird und kein C++ liegt meiner Meinung nach an drei Dingen, allerdings werden Dir hier andere Leute (mit mehr Ahnung) evtl. andere Dinge sagen:

1) Unix ist in C geschrieben. Dadurch ist eine enorme "historische Last" gegeben. Nachfolgende Erweiterungen und auch Ersatz-Code wurde dann ebenfalls in C geschriebene.

2) Einige Open-Source-"Gurus", allen voran Linus Torvalds, sind lautstarke C-Vertreter. Bisher habe ich dafür aber nich nicht viele objektiv korrekte Gründe gehört. Na ja.

3) Viele Programmierer stehen C++' hohem Grad an Abstraktion skeptisch gegenüber. Bei sehr hardwarenahen Komponenten ist es natürlich wichtig, dass Du als Programmierer genau weißt, was gerade passiert. Das ist in C++ nicht unbedingt immer einfach, weil der Standard teilweise recht viele Freiheiten lässt und der Compiler überraschende Optimierungen vornimmt. Torvalds' Hauptargument gegen C++ im Kernelbau z.B. ist, dass das Exception-Modell von C++ teilweise Dinge tut, die man nicht genau genug kontrollieren kann und die daher in einem Kernel nichts zu suchen haben. Nun, da hat er zwar recht, meiner Meinung nach ist das aber kein Grund, C++ grundsätzlich nicht zu verwenden sondern nur, keine Exceptions zu verwenden.

Kommentar von Uwe Gertheinrich am 12.02.2007 um 22:23

Hallo Konrad,

Viele Hardwarenahe Treiber und Interrupt-Routinen und auch RTOS Kernel sind häufig in C oder C++ geschrieben. Liegt das an der von Dir beschrieben Geschwindigtkeit? Sehr oft sind derartige Kernel auch nur in C entwickelt. Ist der Grund hier vielleicht das bessere Multithreading?

Gruß
Uwe

Kommentar von Konrad L. M. Rudolph am 25.01.2007 um 18:38

Hallo Lutz,

schieb bitte nicht die Unfähigkeit des Borland-Compilers der Sprache C++ in die Schuhe. Andere Compiler sind eben besser.

Was den Vergleich zu Assembler und PowerBasic betrifft, so habe ich genau dies in meinem Artikel angesprochen: Natürlich kann man einzelne Code-Teile in Assembler schneller schreiben. Aber keine kompletten Programme. Denn wenn man diese in Assembler genauso effizient schreiben wollte wie in C++, wäre der Arbeitsaufwand unrealistisch groß. Theoretisch geht das vielleicht, praktisch nicht.

Gleiches gilt für PowerBasic: Diese auf deren Homepage zitierten Tests sind alles andere als signifikant. Dass irgendeine kleine Routine in PowerBasic zufällig schneller ist als auf irgendeinem willkürlich gewählten C++-Compiler, sagt doch überhaupt nichts aus, außer, dass der Tester unfähig ist (oder dass er betrügerische Absichten hegt).

Kommentar von Lutz Neumann am 25.01.2007 um 18:14

Das c++ eine schnelle Sprache ist, ist ja wohl eher ein Witz. Die Programme sind bei Borland 5.00 mindestens 400 Kbyte groß, was nur bedeutet das zahlreiche Funktionen aufgerufen werden bevor überhaupt mal was passiert. Bei Borland 6.0 sind es wohl 600 Kbyte. Ich habe mal ein Programm programiert und das lief unter 6.0 so langsam das ich wieder zu 5.0 gewechselt bin. Powerbasicprogramme laufen übrigens schneller und Aseemblerprogramme sind unschlagbar in der Geschwindigkeit, allerdings sehr zeitraubend zu programmieren.

Kommentar von Andreas am 13.01.2007 um 14:23

Hi!

Ok, gebe mich geschlagen. Mir gings au nur drum die c++ Syntax etwas zu verteidigen, weil ich sie auf ihre weise genauso zweckmäßig finde, wie die von VB :)

danke und viele Grüße
andreas

Kommentar von Konrad L. M. Rudolph am 13.01.2007 um 13:07

Hallo Andreas,

> Es muss jedoch explizit angefordert werden, der compiler
> (ansi c++) macht diese Optimierung nicht von sich aus.

Doch, tut er. Moderne Compiler entscheiden größtenteils vollkommen autonom, was sie inlinen und was nicht und können das auch sehr gut. Das lässt sich übrigens leicht überprüfen, indem man einfach eine kleine Funktion *ohne* "inline"-Schlüsselwort aufruft, den Code mit eigenschalteten Optimierungen kompiliert, sich dabei den Assembler-Code ausgeben lässt und anschaut. Man wird sehen, dass der Compiler ein Inlining vorgenommen hat!

Ich habe sogar aus verschiedener Quelle gehört, dass moderne Compiler (VC++ 8, GCC 4) das "inline"-Schlüsselwort vollkommen ignorieren. Das kann ich aber nicht bestätigen. Der Sprachstandard (ANSI C++) erlaubt das aber.

lg,
Konrad.

Kommentar von Andreas am 13.01.2007 um 12:53

Hallo Dirk,
damit hast du natürlich recht, ich bin einfach von dem Fall ausgegangen, dass die Funktion klein genug ist und der compiler das inline akzeptiert :).
Es muss jedoch explizit angefordert werden, der compiler (ansi c++) macht diese Optimierung nicht von sich aus.

Viele Grüße
andreas

Kommentar von Dirk am 12.01.2007 um 07:49

Hallo Andreas,
das ist leider nicht ganz richtig. Inline ist ein "Vorschlag" an den Compiler. Wenn dieser der Meinung ist, es bringt keine Laufzeitvorteile, wird das Inline schlicht ignoriert, wie ich aber bereits anmerkte.

Gruß
Dirk

Kommentar von Andreas Fuchs am 11.01.2007 um 21:54

Hallo!

Du hast einen sehr interessanten Artikel geschrieben und die daraus resultiernde Diskussion ist es auch.
Ich wollt nur anmerken, dass eine als inline deklarierte Methode, keine Methode im eigentlichen Sinn ist. Es findet nämlich kein Programmsprung statt. Stattdessen wird die inline Methode 1:1 an die Methodenaufrufe im Code kopiert und dann normal kompiliert. für kleine, viel verwendete Methoden macht inline also durchaus Sinn, weil die Programmsprünge wegfallen.

ciao, Andreas

Kommentar von Konrad L. M. Rudolph am 09.01.2007 um 16:32

Hallo Dirk,

ich bin geneigt, Dir recht zu geben. Der Satz ist auch nur ein "Disclaimer", falls es doch eventuelle irgendwo eine verquere Situation geben sollte, in der 'inline' etwas bringt. Annahme, wir haben eine riesige Methode, die eine Reihe von Zuweisungen enthält, sonst nicht. Es könnte sein (auch wenn ich das nicht glaube), dass der Aufruf der Methode hier eine Verzögerung darstellt.
Wie dem auch sei, der Satz steht nur da, damit nachher niemand sagen kann "dooooch, 'inline' ist in folgenden Situationen ... ganz doll toll." ;-)

Kommentar von Dirk am 09.01.2007 um 16:15

Schöner Artikel. Ich glaube jedoch, dass folgende die Aussage in "Falsche Voraussetzungen" falsch ist:

<Zitat>Ähnliches gilt für das Schlüsselwort inline. Diese Empfehlung an den Compiler kann man sich ebenfalls getrost schenken, es sei denn, man hat aufwendige Profiling-Tests durchgeführt, die der Compiler evtl. in dieser Form nicht selbst ausführen kann, und hat so herausgefunden, dass der Funktionsaufruf einer großen Methode ein Flaschenhals ist – dieser Fall ist aber extrem selten. </Zitat>

Es scheint mir unwahrscheinlich, dass der Aufruf einer "großen" (was immer das bedeuten soll) Methode ein Flaschenhals ist. Wenn die Methode "groß" ist (ich nehme jetzt an es soll bedeuten, viel zu durchlaufenden Code enthält, evtl Schleifen ...), ist die Zeit, die für den Aufruf verbraucht wird doch wohl eher zu vernachlässigen. Wenn der Aufruf einer Methode, viele Parameter enthält, dann ist die Zeit die für den Aufruf verbraucht wird doch viel mehr von Bedeutung.

So weit ich weiß, ist Inline nur eine Empfehlung an den Compiler und kann von diesem bei Bedarf ignoriert werden.

Gruß
Dirk

Kommentar von thE_iNviNciblE am 08.01.2007 um 09:19

sehr schöner Artikel weiter so :-)

Der Link zu den Benchmarks geht wieder :-)

Gruss
Jan

Kommentar von Fabian Stern am 03.01.2007 um 00:25

Bei mir funktioniert der Link zu Compiler Benchmark's nicht!
Hab dann google angestrengt. Wollte es hier nur einmal bekannt geben!

Kommentar von Markus am 31.12.2006 um 12:10

Hallo,

sehr guter und sachlicher artikel. hätte nur eine frage unter .NET wird doch der vb, c++ sowie auc der c# code in die IL übersetzt und erst am zielcomputer in Maschinencode.

Sollte daher nicht alles ab .NET gleich schnell sein?

verwenden ja den selben compiler nur unterschiedliche interpreter, oder?

mfg Markus

Kommentar von Interflo am 22.12.2006 um 08:53

Sehr guter Artikel, habe einiges dazu gelernt.
Vielen Dank!

Mfg
Flo

Kommentar von Benjamin Schulz am 19.12.2006 um 17:02

Ja, GCs sind definitiv sehr bequem, aber sich daran zu gewöhnen ist tödlich. Wenn die einzigen Ressourcen die man verwaltet irgendwelche Dateien sind, geht das ja alles noch. Neulich musste ich allerdings auf COM zugreifen.. Viel Spaß dabei die Interfacepointer zu releasen, wenn die Objekte out of scope wandern.. Da kann man nur schreien, wenn man auf keinen Dekonstruktor hat..

PS: Ja, der Artikel hat mir auch gefallen, aber deine Beiträge sind auch immer super! (Vorurteilsbedingt erwarte ich sowas auf einer VB-Seite irgendwie nicht - Shame on me!)

Mit freundlichen Grüßen
Benjamin Schulz

Kommentar von Konrad L. M. Rudolph am 19.12.2006 um 12:29

PS: Vielen Dank für den Link, *das* ist mal ein toller Artikel!

Kommentar von Konrad L. M. Rudolph am 19.12.2006 um 12:18

Benjamin,

Du hast natürlich recht. Allerdings ist Speicherverwaltung nochmal ein eigenes Thema für sich. Stroustrup hat allerdings mal sehr schön gesagt „C++ is the best language for garbage collection principally because it creates less garbage.“ Da ist durchaus etwas dran, wie ich auch erwähnt habe: Die STL ist darauf ausgelegt, sowenig Allokationen wie möglich durchzuführen.

Speziell .NET und Java gehen sehr viel freizügiger mit Allokationen um, beispielsweise beim Erstellen temporärer Objekte. Wenn man in .NET mehrere Strings per "a + b + c + d" konkateniert, dann wird für jede der Operationen ein neues temporäres Objekt erstellt. In C++ hingegen kann man gut und gerne davon ausgehen, dass der Compiler das wegoptimiert. Ich weiß leider nicht darüber Bescheid wie aktuelle Compiler das in der Praxis handhaben aber in der C++-Sprachdefinition ist explizit darauf hingewiesen und die gesamte Kopiersemantik von Objekten ist auf solche Optimierungen ausgelegt.

Ein anderes sehr gutes Beispiel ist die Verwendung der Funktion 'sort', welche zur Sortierung beliebiger Objekte einen Parameter mit einem Funktionsobjekt erhält, welches den Größenvergleich übernimmt (standardmäßig 'std::less<>'). Hier muss zwar theoretisch ein neues Objekt erstellt werden, faktisch wird die Erstellung und der Aufruf des Funktionsobjekts aber von aktuellen Compilern komplett ge-inlined. In Java und .NET geht das nicht, da hier ein polymorphes Objekt verwendet wird, welches eine Schnittstelle implementiert.

Aber trotz all dieser Argumente gebe ich Dir recht, dass man in C++ sehr darauf achten muss, seine Programme so zu schreiben, dass solche Optimierungen stattfinden können. Gerade const-correctness kann echt anstrengend sein! In Umgebungen wie .NET und Java hat man es hier definitiv einfacher, da die modernen GCs wirklich wahre Technikwunder sind, die Speicherverwaltung stark beschleunigen. Das habe ich in dem Absatz "Falsche Voraussetzungen" ja auch kurz angedeutet.

MfG,
Konrad.

Kommentar von Benjamin Schulz am 19.12.2006 um 01:37

So ganz stimmt das mit dem Geschwindigkeitsvorteil von C++ nicht mehr. Bei der Datenverarbeitung passiert es nicht selten, dass Objekte erstellt und kurz danach wieder verworfen werden. Wenn man an dieser Stelle in C++ nicht sehr vorsichtig programmiert um die dahinterstehenden allocs und deallocs zu vermeiden, können die GC-basierten Systeme (Java, .NET, uvm.) schneller sein.

Siehe auch: http://www-128.ibm.com/developerworks/java/library/j-jtp09275.html

Ansonsten sehr guter Artikel! Hatte nicht erwartet so unwissend zu sein.. :P

Mit freundlichen Grüßen
Benjamin Schulz

Kommentar von JonasW am 17.12.2006 um 15:42

Echt toll!

Jetzt ist mir vieles klar geworden!

Danke

Kommentar von Mathias am 11.12.2006 um 12:07

Kann mich Hans-Jörg nur anschließen. Danke für die Mühe.
Ein sehr guter Artikel.

Kommentar von Hansjörg M. Schmauder am 02.12.2006 um 12:26

Ein toller Artikel für die Kolumne, hat mir richtig Spaß gemacht, ihn zu lesen, danke Konrad!

Grüße, HMS