performance von C und gegenüber C++



  • hallo leute,

    ich habe da gerade eine diskussion mit einem bekannten laufen, der meint, dass C schneller ist als C++. ich bin der meinung, dass man mit C++ (also objektorientiert und templates) vielleicht sogar noch
    schnellere programme auf bequemere art und weise erstellen kann. hängt halt vom programmierstil ab.

    ich wollte euch fragen, was ihr zu diesem thema sagt. welche konstrukte in C++ sind denn langsamer?
    ich würde sagen folgende "könnten" langsamer sein:

    - evt. polymorphie (also virtuelle methoden), aber in C hätte man dann wahrscheinlich einen riesen switch-case block.

    - evt. ein try-catch-block mit exceptions. in C hätte man dann allerdings irgendwelche "if-orgien"

    was meint ihr?

    Gruß mathik



  • C++ ist nicht langsamer als C - allerdings gibt es einige langsame Standard Library Implementationen 😞

    C++ ermöglich aber auch neben Templates nette Optimierungen: Functoren - die können nämlich, im gegensatz zu Funktionszeiger, geinlinet werden.

    Teste mal std::sort gegen qsort() 🙂



  • ich habe da gerade eine diskussion mit einem bekannten laufen, der meint, dass C schneller ist als C++.

    Was schneller? Schneller müde? Schneller langweilig? Schneller erlent? Schneller geparst? Schneller compiliert?
    Einige von diesen Eigenschaften sind auf jeden Fall richtig.

    Wenn es aber um die Ausführungseffiziens geht, dann ist diese Aussage in dieser Form käse.

    ich wollte euch fragen, was ihr zu diesem thema sagt. welche konstrukte in C++ sind denn langsamer?

    Das ist eine sehr eigenartige Frage. Normalerweise benutzt man langsamer im Vergleich. Also: "A ist langsamer als B". Statt nur "A ist langsamer".

    Also müssen wir die Konstrukte in C++ mit etwas vergleichen. Vergleicht man die Konstrukte von C++ mit denen von C, dann kann aber z.B. schon mal nicht ohne weiteres sowas wie virtuellen Methoden betrachten, da C solche nicht kennt. In diesem Fall muss man also genauer definieren, wie man ein Konstrukt A in C++ abbilded auf ein oder mehrere C Konstrukte.

    Bleibt zuerst der direkte Vergleich: Du nimmst ein Programm P und betrachtest es einmal als C und einmal als C++ Programm.
    Unterschied theoretisch: Keiner.
    Unterschied praktisch: Abhängig von der Qualität deiner Compiler.

    Eine Funktion in C++ lässt sich also z.B. genauso effizient aufrufen wie eine Funktion in C.

    Jetzt betrachten wir mal ein paar neue Konstrukte:
    Behauptung: Überladung macht C++ Funktionen doch bestimmt viel langsamer?
    Antwort: Nein. Überladung ist eine Compilezeitangelegenheit und hat keinen Einfluss auf die Laufzeit einer Funktion bzw. auf die Aufrufgeschwindigkeit

    Behauptung: Methodenaufrufe sind langsamer als Aufrufe normaler C-Funktionen
    Antwort: Richtig, aber Äpfel mit Birnen verglichen. Der Unterschied resultiert daraus, dass eine Methode neben ihren expliziten Parametern immer noch einen impliziten Parameter (nämlich einen Zeiger auf das aktuelle Objekt) besitzt.
    Über diesen Zeiger ist es der Methode möglich auf die Daten des Objekts zuzugreifen.
    Was in C++ die Form:

    foo.bar();
    

    hat, hat in C die Form:

    bar(foo);
    

    In diesem Fall ist der Unterschied also gleich null.

    Behauptung: virtuelle Funktionen sind im Aufruf langsamer als normale C-Funktion.
    Antwort: Richtig, aber Äpfel mit Birnen verglichen. Virtuelle Funktionen sind in C++ optional. Ihr Einsatz geschieht dann, wenn man sie braucht. Sprich: wenn man das Verhalten einer Methode verwandter Typer variieren möchte.
    In C kann man virtuelle Funktionen schlecht und gut simulieren. Entweder man verwendet einen switch-on-type oder in Strukturen eingebettete Funktionspointer. Beide Varianten sind in der Regel nicht effizienter als virtuelle Methoden.

    Natürlich gibt es auch Situationen in den ein simpler switch-on-type-C-Ansatz schneller ist. In diesem Fall tauscht man aber Geschwindigkeit gegen Flexibilität. Und nicht vergessen: Da virtuelle Methoden in C++ optional sind, kann man immer auch auf sie verzichten.

    Behauptung: Exceptions sind langsamer als Fehlercodes
    Antwort: Richtig, aber im Normalfall völlig uninteressant?
    Ich schreibe "im Normalfall", da es hier auch echte Ausnahmen gibt.
    Die Performance von Code mit Exceptions ist extrem Compilerabhängig. Es gibt leider nach wie vor Compiler, bei denen Exceptions immer etwas kosten, egal ob tatsächlich eine fliegt oder nicht. Das kann in extrem performance-kritischen Systemen ein echtes Problem sein, weshalb hier schonmal auf Exceptions verzichtet wird.
    Auf der anderen Seite muss das nicht so sein. Gute Compiler können Code generieren, bei dem die Kosten erst entstehen, wenn wirklich eine Exception geworfen wird. Und wann passiert das? Richtig. Nur in Ausnahmesituation, also selten. In einer Ausnahmesituation hat man für gewöhnlich aber ganz andere Probleme als Performance.

    So könnte man das nun stundenlang weiterführen. Der Sinn ist imo aber fragwürdig. Zum einen gibt es bereits viele gute Quellen zu diesem Thema (im Internet oder z.B. auch Lippmans "Inside the C++ Object Model") zum anderen riecht ein solcher Thread imo immer nach "Optimierung auf der falschen Ebene".

    Man schreibt Software in der Regel immer mit konkreten Anforderungen. Und für konkrete Anforderungen eignet sich eine Sprache, ein Compiler oder eine Herangehensweise mehr oder weniger gut. Eine Lösung wird aber nicht dadurch unbrauchbar, dass man statt C C++ eingesetzt hat. Oder statt einer normalen Funktion eine virtuelle. Bevor man sich über solche Nanooptimierungen den Kopf zerbricht sollte man imo erstmal an anderen Schrauben drehen: Hardware, Compiler, Algorithmen.

    Generell kann man aber sagen, und das ist wohl der einzig wichtige Satz in diesem Posting:
    Ein Problem das sich zufriedenstellend mit C lösen lässt, lässt sich ebenso auch mit C++ lösen.



  • mathik schrieb:

    - evt. ein try-catch-block mit exceptions. in C hätte man dann allerdings irgendwelche "if-orgien"

    die theorie sagt das es mit exception schneller geht, wenn du bei jeden kleinen funktions aufruf ein if machen muss um zu sehen ob alles ok gelaufen ist
    irgend wann hatt man erstmal die nasse voll jede kleine funktion abzufragen, die prüfungen versperen einen den blick auf das wesentliche
    außerdem
    funktion_a ruft funktion_b auf und funktion_b ruft funktion_c auf, wenn funktion_c jetzt ein fehler macht, wird der fehler einmal in funktion_c gefunden, bearbeitet und an funktion_b zurückgegeben, funktion_b stellt jetzt diesen fehler auch fest (finden/bearbeiten/zurückgeben), das gleiche haben wir dann in funktion_a usw.

    d.h. die fehler von funktion_c werden in diesen bsp drei mal bearbeitet

    in der praxis soll exception-code langsammer sein, war zumindestenz in vc6.0 so 😞
    aber meine test mit vc2003 haben kein unterschied gezeigt (vielleicht waren meine test nicht gut genug)



  • HumeSikkins schrieb:

    Generell kann man aber sagen, und das ist wohl der einzig wichtige Satz in diesem Posting:
    Ein Problem das sich zufriedenstellend mit C lösen lässt, lässt sich ebenso auch mit C++ lösen.

    Allerdings ist die naheliegende Lösung dann kein C++ mehr. Das ist wenigstens die Meinung, die ich aus zahlreichen Artikeln im C++-Forum deduzieren konnte.



  • hallo leute,

    danke erstmal für eure beiträge.

    ich habe da allerdings noch ein paar fragen:
    wieso wird im embedded bereich denn immer noch so oft in C programmiert? ich meine ok, wenn jetzt kein C++ compiler zu verfügung steht, dann ist das ja ok, aber warum dann, wenn einer da ist (insbesondere auch ein BS wie QNX). da kommt dann meinstens das argument, C sei schneller, was ich überhaupt nicht nachvollziehen kann (ihr ja auch nicht ;))

    und warum wird denn überhaupt noch so viel in C programmiert? siehe z.b. die ganze software unter Linux (apache, samba, usw.) .



  • HumeSikkins schrieb:

    ich habe da gerade eine diskussion mit einem bekannten laufen, der meint, dass C schneller ist als C++.

    Was schneller? Schneller müde? Schneller langweilig? Schneller erlent? Schneller geparst? Schneller compiliert?
    Einige von diesen Eigenschaften sind auf jeden Fall richtig.

    Wenn es aber um die Ausführungseffiziens geht, dann ist diese Aussage in dieser Form käse.

    ich wollte euch fragen, was ihr zu diesem thema sagt. welche konstrukte in C++ sind denn langsamer?

    Das ist eine sehr eigenartige Frage. Normalerweise benutzt man langsamer im Vergleich. Also: "A ist langsamer als B". Statt nur "A ist langsamer".

    @hume
    mit performance meine ich, wie du es ja schon richtig erkannt hast, die laufgeschwindigkeit des programms. 😉
    warum soll das denn käse sein?
    ich könnte ja behaupten ein sehr guter C-programmierer kann ein programm schreiben, das schneller ist als das äquivalente eines sehr guten C++-programmierers, der das ganze objektorientiert macht. oder nicht?
    oder auch, dass alle C++ programme langsammer sind als die äquivalenten C programme, weil die objektorientierung einfach zu viel overhead produziert.

    im internet finde ich zu dem thema leider auch nichts. vielleicht kannst du mir ja einen link posten, wenn du eins hast. 🙄



  • mathik schrieb:

    wieso wird im embedded bereich denn immer noch so oft in C programmiert?
    [..]
    da kommt dann meinstens das argument, C sei schneller

    Weil es oft keinen C++ gibt - bzw. es aufwendig ist, einen C++ Compiler zu schreiben. C ist da wesentlich einfacher zu handlen.

    Und teilweise liegt es auch an falschem wissen. zB dass C++ langsamer sei, oder dass template mehr Speicher fressen, etc.

    Dabei habe ich letztens einen alten Artikel in comp.std.c++.moderated oder comp.lang.c++.moderated (weiss nicht mehr) gelesen. Templates haben auf embedded systemen einen großen Vorteil: es werden immer nur die funktionen instanziiert die auch gebraucht werden - bei einer 'normalen' klassen, werden ja immer alle Methoden instanziiert.

    allerdings muss man auch zugeben, dass schlechte c++ compiler schlechten code erzeugen. Gerade bei Exceptions und templates kann es sein, das alte bzw. schlechte Compiler echt miesen code erzeugen - und vorallem: an sowas erinnert man sich dann ewig. auch wenn die compiler besser geworden sind.

    Selbiges hast du übrigens bei der Spieleprogrammierung (zumindest der hobbymäßigen). Denn die meisten Spieleprogrammierungsbücher erzählen so einen quark 😞

    ich könnte ja behaupten ein sehr guter C-programmierer kann ein programm schreiben, das schneller ist als das äquivalente eines sehr guten C++-programmierers, der das ganze objektorientiert macht. oder nicht?
    oder auch, dass alle C++ programme langsammer sind als die äquivalenten C programme, weil die objektorientierung einfach zu viel overhead produziert.

    ja, behaupten kannst du es, aber das macht die aussage auch nicht richtig.

    es gibt eben kein direktes äquivalent zu virtual in C. Sicher, man kann es simulieren - aber du erreichst damit nicht die flexibilität wie das echte virtual.

    Und das eine 'kann 70% von dem was virtual kann' implementation uU eine kleine spur schneller läuft ist damit begründet, dass es einfach nicht alles kann was virtual kann. Wenn man dann nämlich diese restlichen 30% braucht, wirds in C vermutlich im längen langsamer...

    Wenn man aber einfach sagt: switch VS virtual - da schneidet virtual zumindest nicht signifikant schlechter ab.

    irgendwann habe ich mal was von einem prozessor gehört, der einen virtual call als opcode implementiert hat - da ist switch natürlich wieder langsamer. (allerdings habe ich das nur gehört, und kann nix konkretes sagen - auch nicht ob es überhaupt stimmt)

    OOP erzeugt nicht zwangsläufig Overhead - gute compiler optimieren da 'wie sau'. schlechte Compiler bauen natürlich auch viel mist.

    ob man
    void f(foo* this);

    oder
    void foo::f();

    hat - ist ja egal - der generierte code wird sehr ähnlich sein (wenn nicht uU sogar gleich)

    Bei vergleichen C mit C++ wird aber oft der Fehler gemacht zu sagen:

    void foo(void);
    ist schneller als
    void Class::foo();

    -> ist ja auch logisch, dass das stimmt. aber die beiden konstrukte sind ja auch nicht identisch...

    c++ bietet eine Menge möglichkeiten den Code schneller zu machen, die C nicht hat. zB expression templates oder das functoren geinlinet werden können, etc.

    ich glaube also kaum, dass ein C++ Programm signifikant langsamer oder schneller als ein äquivalentes C programm laufen wird.



  • Wenn C++ wirklich so performant wäre, wie es C-Compilate unbestritten sind, stellt sich die Frage, warum gängige Betriebssysteme noch immer in C und nicht in C++ geschrieben werden.



  • gast i.s.b.
    ***********

    ich vermute mal, weil die vielleicht keinen bock haben ihre hunderttausende von quellcodezeilen umzuschreiben? man könnte das ja alles nach c++ portieren, nur siehts dann immernoch wie C aus 😉 sprich man braucht auch ne komplette redesignphase/neuschreibphase...und rechtfertigt das den aufwand? ich vermute weiter wenn du nen OS schreibst brauchste ja auch irgendwann ein compiler für dein system und ein C compiler ist da glaub ich schneller entwickelt als C++ (zumindest ist der C standard von den ausmaßen sicher nur ein drittel vom c++ standard)

    tschööö

    tt



  • Gast ist schon belegt schrieb:

    Wenn C++ wirklich so performant wäre, wie es C-Compilate unbestritten sind, stellt sich die Frage, warum gängige Betriebssysteme noch immer in C und nicht in C++ geschrieben werden.

    und was ist mit win2000 (drauf aufbauend winxp, win server 2003, win longhorn usw.)?

    klar ist linux noch in c und windows würde auch noch in c sein, wenn ms nicht so viel geld hätte und sich gedacht hatt: ok wir vergessebn den win9x & winnt code und schreiben alles neu, aber diesmal sauber und in c++

    mathik schrieb:

    und warum wird denn überhaupt noch so viel in C programmiert? siehe z.b. die ganze software unter Linux (apache, samba, usw.) .

    weil sie keine zeit haben die software neu in c++ zu schreiben



  • Hallo,
    C++ != Objektorientier. Das sollte man immer bedenken, bevor man irgendwelche Aussagen trifft.

    wieso wird im embedded bereich denn immer noch so oft in C programmiert?

    Immer langsam. So schnell geht das mit dem Wechsel nicht. Es hat viele Jahre gedauert, bis im Embedded-Bereich im Großen Stil C statt Assembler benutzt wurde. Und es wird viele Jahre dauern, bis C++ statt C verwendet wird. Wenn man sich aber mal ein bischen in der Embedded-Literatur-Welt umschaut, wird man feststellen, dass C++ immer häufiger ein Thema wird (siehe z.B. Embedded Systems Programming)

    Eins sollte aber relativ klar sein: Niemand der 4k Speicher zur Vrfügung hat wird sein Steuerungsprogramm schön Objektorientiert aufbauen, fein mit Hierarchien, virtuellen Methoden und vielen kleinen Objekten. Die OOP hat gute Anwendungsgebiete, aber nicht alles was programmiert werden muss, sollte oo programmiert werden. Dennoch: auch wenn man auf oop verzichtet hat C++ gegenüber C Vorteile.

    im internet finde ich zu dem thema leider auch nichts. vielleicht kannst du mir ja einen link posten, wenn du eins hast

    Nachher vielleicht. Jetzt muss ich los.



  • Ein wichtiger Grund ist auch, dass C++-Compiler um Größenordnungen schwerer zu entwickeln sind als C-Compiler, und zwar zwar hauptsächlich wegen der komplizierteren Semantik. Kleine Klitschen, die C-Compiler für embedded-Systeme bauen, kümmern sich lieber um Code-Optimierung als um Name-Lookup oder Überladungsauflösung.



  • Bashar schrieb:

    [..] Kleine Klitschen, die C-Compiler für embedded-Systeme bauen, kümmern sich lieber um Code-Optimierung als um Name-Lookup oder Überladungsauflösung.

    Jetzt hätt ich einmal auch nen gutes Argument gehabt um mitzureden und dann im
    letzten Posting ist mir einer zuvorgekommen 😞 😉



  • @Shade
    das Argument mit den Templates verstehe ich nicht

    #include <cstdio>
    
    template<class T> T foo(int c) { return c/static_cast<T>(2); };
    
    int main() {
      std::printf("%f\n",foo<float>(5));
      std::printf("%d\n",foo<int>(5));
    }
    
    #include <stdio.h>
    
    int foo_int(int c) { return c/2; }
    float foo_float(int c) { return c/(float)2; }
    
    int main() {
      printf("%f\n",foo_float(5));
      printf("%d\n",foo_int(5));
      return 0;
    }
    

    sollte ja die gleiche Code größe ergeben. Dachte Templates sind nützlich, weil man Code spart und nicht für jeden Fall alles neu implementieren muss (und noch ein paar andere Tricks). Aber ich denke nicht, dass die Binarys deswegen kleiner werden.

    zB dass C++ langsamer sei

    Ich denke eher, dass die Leute in dem Fall mehr an die Binary größe denken, aber die ist ja bei C++ gleich (wenn man die C++ Standard-Library nicht linkt, die auf Embedded Systemen ja eh nicht vorhanden ist)



  • kingruedi schrieb:

    @Shade
    das Argument mit den Templates verstehe ich nicht

    weil dus falsch verstanden hast 😉

    Ich meine nur bei Member Funktionen (habe ich nicht explizit geschrieben, weil ich dachte dass es klar ist - aber jetzt wo ichs nochmal gelesen habe -> du hast recht, ist nicht klar ersichtlich).

    Denn es werden nur die Member Funktionen von Template Klassen instanziiert, die auch gebraucht werden, die anderen nicht. Bei 'normalen' non-Template Klassen werden alle Member Funktionen instanziiert.

    Dies ist natürlich normalerweise ziemlich egal - aber gerade auf Embedded Systemen kann es Vorteile bringen.



  • Wer sagt denn, dass alle Memberfunktionen von nicht-Template-Klassen "instanziiert" werden müssen? Es gibt kein konformes Programm, dass feststellen kann, dass eine Memberfunktion nicht instanziiert wurde, also steht es dem Übersetzer frei, die Definition im Executable nicht einzubinden, wenn sie nicht angesprochen wird.





  • Das mag bei dem einen Compiler so sein. Generell sagen kann man das mit Sicherheit nicht. Die Frage ist nur, ob der Compiler (bei Templates) oder der Linker (bei nicht-Templates) schlau sein muss.
    Dass Memberfunktionen von Templates nicht instanziiert werden, hat eigentlich nur den Effekt, dass in diesen Funktionen nicht nach Fehlern gesucht wird. Beispiel vector<T>::resize für ein T ohne Standardkonstruktor -- macht nichts, solange resize nicht aufgerufen und damit instanziiert wird.



  • mathik schrieb:

    im internet finde ich zu dem thema leider auch nichts. vielleicht kannst du mir ja einen link posten, wenn du eins hast

    HumeSikkins schrieb:

    Nachher vielleicht. Jetzt muss ich los.

    So, jetzt bin ich wieder da.

    Teste mal std::sort gegen qsort()

    Bitte schön

    OOP erzeugt nicht zwangsläufig Overhead - gute compiler optimieren da 'wie sau'

    Stichwort: Abstraction Penalty

    Geschwindigkeit dank Templates:
    Bitte schön
    Bitte schön

    Ein paar simple Vergleiche:
    Comparing C++ and C Performance I

    Comparing C++ and C Performance II


Anmelden zum Antworten