Warum ist C so schnell?



  • vista schrieb:

    rapso schrieb:

    c++ ist schonwieder ne andere geschichte 😉

    nicht wirklich.
    dem makroassembler wurden nur einfach ein paar makros mehr spendiert.
    🙂

    doch wirklich! ausfuehrungsgeschwindigkeit und sehr direktes mappen auf maschinensprache war nicht mehr zielrichtung, denn das hatte man ja mit c schon. viele dinge wurden so aufgebaut, dass es "sehr viel potential" fuer optimierungen gab fuer die compilerhersteller.



  • @rapso: Sehe ich genauso!

    C ist ziemlich einfach auf Assembler und somit auch auf Maschinencode abzubilden. Es gibt so gute wie keine Abstraktionsmechanismen. Dadurch ist C sehr schnell und schlank. Bei C++ ist das so eine Sache. Die Abstraktionsmittel die man verwendet erhöhen die Produktivität und können je nach Compiler und verwendeter Standardlib durchaus langsameren Maschinencode als ein äquivalentes C Programm liefern. Templates und komplexe Klassenhierarchien mit Polymorphie sind halt viel schwieriger auf Assembler abzubilden, als einfache Funktionen und Variablen.



  • /. schrieb:

    Templates und komplexe Klassenhierarchien mit Polymorphie sind halt viel schwieriger auf Assembler abzubilden, als einfache Funktionen und Variablen.

    Aber einfacher als du denkst. Templates sowieso, die sind schwer zu parsen, aber nach der Instanziierung unterscheiden sie sich nicht mehr wirklich von normalem Code und können dann straight-forward auf Maschinencode abgebildet werden. Virtuelle Funktionen sind auch kein Problem, das ist nicht viel mehr als sowas wie (obj->vtable[2])() in C.
    Ich schätze Exceptions sind am schwierigsten umzusetzen.



  • Bashar schrieb:

    Ich schätze Exceptions sind am schwierigsten umzusetzen.

    vielleicht benutzen die intern setjmp/longjmp?
    richtige exceptions wie 'division durch 0' o.ä. sind aber bestimmt nicht einfach abzufangen...



  • Bashar schrieb:

    /. schrieb:

    Templates und komplexe Klassenhierarchien mit Polymorphie sind halt viel schwieriger auf Assembler abzubilden, als einfache Funktionen und Variablen.

    Aber einfacher als du denkst. Templates sowieso, die sind schwer zu parsen, aber nach der Instanziierung unterscheiden sie sich nicht mehr wirklich von normalem Code und können dann straight-forward auf Maschinencode abgebildet werden. Virtuelle Funktionen sind auch kein Problem, das ist nicht viel mehr als sowas wie (obj->vtable[2])() in C.
    Ich schätze Exceptions sind am schwierigsten umzusetzen.

    es geht ja nicht nur um den aufwand der umsetzung, sondern wie das performancemaessig dann ausschaut. ich denke gerade die ersten compiler haben alles erstmal nur funktional gemacht und nicht nach geschwindigkeit optimiert. quasi so wie es mit c war, nur war es bei c dann schon relativ optimal, weil direkt auf microcode gemappt.
    und auch wenn es dann einigermassen optimiert wurde, hat man oft kein direktes mapping auf den microcode. vtables sind z.b. fuer viele cpus der tod, sie werden wie falsch vorhergesagte spruenge behandelt und stallen die ganze pipeline. sind aber eines der grundkonzepte fuer polymorphismus. bei c hatte man jumptables nur explizit benutzt und nur an stellen die wirklich dann performance bekommen.



  • vista schrieb:

    Bashar schrieb:

    Ich schätze Exceptions sind am schwierigsten umzusetzen.

    vielleicht benutzen die intern setjmp/longjmp?

    die implementation davon ist nicht sonderlich einfach wegen den ganzen dingen die dabei beruecksichtig werden muessen wie z.b. destructoren von local variablen aufrufen usw.

    richtige exceptions wie 'division durch 0' o.ä. sind aber bestimmt nicht einfach abzufangen...

    doch sind sie, das macht die cpu fuer dich indem sie einen interrupt aufruft.



  • rapso schrieb:

    richtige exceptions wie 'division durch 0' o.ä. sind aber bestimmt nicht einfach abzufangen...

    doch sind sie, das macht die cpu fuer dich indem sie einen interrupt aufruft.

    ja, aber dann bekommt man eine fehlermeldung vom OS und das programm steigt aus.
    kann man sowas überhaupt mit einem C++ 'catch' fangen? wenn überhaupt, ist es doch bestimmt systemabhängig...
    🙂



  • vista schrieb:

    rapso schrieb:

    richtige exceptions wie 'division durch 0' o.ä. sind aber bestimmt nicht einfach abzufangen...

    doch sind sie, das macht die cpu fuer dich indem sie einen interrupt aufruft.

    ja, aber dann bekommt man eine fehlermeldung vom OS und das programm steigt aus....

    Eben genau das, was eben passiert .... 😉
    Sowas wird ebensowenig standardmäßig mit exception abgefangen wie seg-faults...

    Gruß,

    Simon2.



  • vista schrieb:

    Bashar schrieb:

    Ich schätze Exceptions sind am schwierigsten umzusetzen.

    vielleicht benutzen die intern setjmp/longjmp?

    Ne, du musst ja noch den Stack aufrollen (also im C++-Sinne mit Destruktoren)

    richtige exceptions wie 'division durch 0' o.ä. sind aber bestimmt nicht einfach abzufangen...

    Das ist ja auch keine Exception im C++-Sinne. Wobei man hier auch noch 'division durch 0.0' unterscheiden muss 🙂



  • rüdiger schrieb:

    Und Assembler ist schnell.

    Zuviel overhead?



  • mit luft in der hand schrieb:

    rüdiger schrieb:

    Und Assembler ist schnell.

    Zuviel overhead?

    Was ich meinte: Assembler ist nicht per Definition schnell. Das wird imho immer falsch vermittelt. Heutige CPUs sind derart komplex, dass die Compiler dort deutliche Vorteile gewinnen. Um effiziente Programme in Assembler zu schreiben, muss man schon ein ziemlich guter Assembler Programmierer sein und die Details der CPU sehr gut kennen.



  • rüdiger schrieb:

    ...und die Details der CPU sehr gut kennen.

    Und dementpsrechend auch CPU optimieren, denk ich mal, während man beim Compiler einfach einen schalter setzt der auf eine bestimmte CPU optimiert ohne dass man Code ändern muss.



  • rüdiger schrieb:

    Was ich meinte: Assembler ist nicht per Definition schnell. Das wird imho immer falsch vermittelt. Heutige CPUs sind derart komplex, dass die Compiler dort deutliche Vorteile gewinnen. Um effiziente Programme in Assembler zu schreiben, muss man schon ein ziemlich guter Assembler Programmierer sein und die Details der CPU sehr gut kennen.

    Ja ich weiß, aber das ist genauso wie zu behaupten C ist nicht schnell, weil die meisten Programmierer zu dumm sind es richtig einzusetzen.



  • mit luft in der hand schrieb:

    rüdiger schrieb:

    Was ich meinte: Assembler ist nicht per Definition schnell. Das wird imho immer falsch vermittelt. Heutige CPUs sind derart komplex, dass die Compiler dort deutliche Vorteile gewinnen. Um effiziente Programme in Assembler zu schreiben, muss man schon ein ziemlich guter Assembler Programmierer sein und die Details der CPU sehr gut kennen.

    Ja ich weiß, aber das ist genauso wie zu behaupten C ist nicht schnell, weil die meisten Programmierer zu dumm sind es richtig einzusetzen.



  • rüdiger schrieb:

    mit luft in der hand schrieb:

    rüdiger schrieb:

    Was ich meinte: Assembler ist nicht per Definition schnell. Das wird imho immer falsch vermittelt. Heutige CPUs sind derart komplex, dass die Compiler dort deutliche Vorteile gewinnen. Um effiziente Programme in Assembler zu schreiben, muss man schon ein ziemlich guter Assembler Programmierer sein und die Details der CPU sehr gut kennen.

    Ja ich weiß, aber das ist genauso wie zu behaupten C ist nicht schnell, weil die meisten Programmierer zu dumm sind es richtig einzusetzen.

    doch



  • C ist auch nicht per Definition schnell.

    (Und bei Assembler dürfte die Situation ja eher so sein, dass die meisten Leute schlechter sind als ein guter Compiler (ok vielleicht x86 ausgenommen, weil das so wenig Register hat, das man da mit ner manuellen Register-Verwaltung noch etwas rausholen kann))



  • Sagtmal, was eigentlich diskutiert ihr da überhaupt? Ob die Sprache C schnell ist? - Hallo?

    Wenn ihr diskutieren würdet wieso der GCC Compiler so guten Code erzeugt, oder wieso der Intel-C-Compiler ein so schlechten Code erzeugt, das würde ich ja noch verstehen.

    Genauso könnte man einen C-Compiler bauen der so lahmen Code erzeugt, dass interpretiertes BASIC wie Assembler aussieht. Aber stattdessen wird hier diskutiert das C besser ist als Assembler weil das per definition schneller ist und einfacher zu parsen von einem Compiler wäre. Wenn ich Zeit hätte würde ich einen ASM-Interpreter schreiben, dann würdet ihr darüber diskutieren wieso die ASM-Sprache so lahm wäre...

    Wäre C seit Heute die neuste Neuheit auf dem PC, dann würdet ihr eher diskutieren wieso C so unglaublich lahm ist, das Pascal-Programme dagegen wie Überschallflieger aussehen.

    Weil der Code i.d.R. direkt in Maschinensprache umgesetzt wird, d.h. ohne Umwege von der CPU ausgeführt wird.

    Das kann man mit jeder X-beliebigen Sprache auch machen, man muss nur einen Compiler schreiben der das macht.

    C ist auch nicht per Definition schnell.

    Echt nicht? Ich dachte bei der Sprache C kann jeder Compiler eine Kristallkugel befragen, so das dieser den Code für 100 Jahre im vorraus und für jede Eventualität vorherberechnen kann. Gibt es in C das Schlüsselwort magic nicht? Meine Sprache hat das. 🤡



  • DEvent schrieb:

    Sagtmal, was eigentlich diskutiert ihr da überhaupt? Ob die Sprache C schnell ist? - Hallo?

    Ebenfalls Hallo! Deine Belehrungen in Ehren, aber bitte stell dich nicht um der Klugscheisserei willen duemmer als du bist. Dass es hier um die Implementierungen von C geht und darum, warum gaengige C-Compiler derart schnellen und effizienten Code liefern, liegt ja wohl auf der Hand 😉

    EDIT: wobei ich doch sehr wohl glaube dass die Sprache C einige Merkmale hat, die es einfacher machen, den Code auf Geschwindigkeit zu optimieren, waehrend man bei anderen Sprachen bewusst auf gewisse Moeglichkeiten verzichtet hat, um die Sprache einfacher zu machen.



  • DEvent schrieb:

    Weil der Code i.d.R. direkt in Maschinensprache umgesetzt wird, d.h. ohne Umwege von der CPU ausgeführt wird.

    Das kann man mit jeder X-beliebigen Sprache auch machen, man muss nur einen Compiler schreiben der das macht.

    Manche Sprachen eignen sich aber nur bedingt dazu, von Compilern direkt in effizienten Maschinencode überführt zu werden. Bei nicht-imperativen Sprachen gibt es sogar überhaupt keine direkte Übersetzung.
    Was nicht heißt, dass sie nicht effizient übersetzt werden können, aber die Gründe liegen dann nicht -- wie bei C -- in der Direktheit, sondern darin, dass die Semantik so abstrakt ist, dass die Compiler gut optimieren können und Code dann effizinten Code erzeugen, der aber mit dem Quellprogramm nicht mehr viel gemeinsam hat.



  • es gibt z.b. prozessoren, die keinen stack, keine call/ret instructions, dafür aber übelst viele register haben. weil c-programmierer unheimlich gerne funktionen, lokale variablen und manchmal rekursion verwenden, ist so eine CPU schon eine kleine herausforderung für compilermacher...
    🙂


Anmelden zum Antworten