Entsteht bei C++ ein theoretischer overhead?
-
Wissensdurstige schrieb:
Ein Beispiel ist vielleicht Doom3. Doom3 ist ja bis auf die Grafik-Engine in C++ geschrieben. Aber warum wurde ausgerechnet die 3d-Engine in C erstellt? Das die/der Programmierer C++ nicht beherrschen denke ich nicht, denn sonst hätten sie das gesamte Spiel in C geschrieben.
Ich habe auch schon öfters gehört das C hardwarenäher ist, was mir ebenfalls nicht einleuchtet, da ich ja mit C++ die komplette C Funktionalität zur Verfügung habe.
Naja das liegt glaub ich eher an dem Typen, der die Grafikengine codet. Muss man halt auch respektieren, warum soll er sich jetzt noch umgewöhnen?
-
Daran liegts sicherlich nicht :D. Good old Johnny ist in der Lage C++ zu programmieren - und alleine schreibt er die Engines sicherlich auch nicht mehr
MfG SideWinder
-
Ich sags dir, ich trau dem ganz ehrlich zu, dass er C++ nicht soooo gut kann. Er ist mit Sicherheit kein schlechter Coder, aber vielleicht hat er sich ja über die Jahre hinweg mit C den Stil versaut??
Naja ok, das sind jetzt nur böse Mutmaßungen, ich frag ihn mal, wenn ich ihn nächstes mal wieder sehe.
-
Wissensdurstige schrieb:
Mir geht schon seit einiger Zeit ein berühmtes Gerücht nicht aus dem Kopf. Entsteht bei der C++ Programmierung ein overhead? Ob er vernachlässigbar ist, ist egal. Es geht dabei rein um die Theorie.
gegenüber assembler ist ein overhead da, weil gar nicht alle assemberbefehle in der sprache verfügbar sind. in asm kann man fein zwei zahlen addieren und dann springen, falls es einen überlauf gab. dieses "falls es einen überlauf gab" ist in c++ nicht direkt ausdrückbar. bei solchen sachen passiert es, daß asm schneller ist.
Man hört auch das insbesondere auf nicht X86 Architekturen ein C Compiler bessere Arbeit macht als ein C++ Compiler. Ist da etwas wares dran?
nichts. gar nichts.
aber altes fortran ist schneller. insbesondere, wenn der prozessor keinen stack hat. denn in fortran ist auch kein stack vorgesehen. in c und c++ aber wohl. das simulieren eines stacks macht auf diesen kisten die sache nicht wirklich schneller.Ich würde nicht wegen 2 jumps mehr die Programmiersprache wechsel, bin aber sehr Wissensgierig.
Ich kann mir halt nicht vorstellen das ein Objekt, welches ein anderes Objekt hält und ich dessen Methoden aufrufen möchte gleich schnell ist, als ob ich direkt die Funktionen aufrufen würde(ala C).
ein objekt, das ein andertes objekt hält.
class Motor{ int leistung; void anzeigeLeistung(){ cout<<leistung<<endl; } }; class Auto{ Motor m; }; ... Auto *a; ... a->m.anzeigeLeistung();
das ist billig.
a->m löst der compiler ja als (Motor)(((char*)a)+offsetM). also nur gecasste, damoit's syntaktisch klappt und einer addidion mit ner konstanten. hier hat die konstante sogar den wert 0 und fliegt raus.
und
a->m.anzeigeLeistung();
ist innendrin nix anderes als
anzeigeLeistung(&a->m);
also ein normaler funktionsaufruf, der als erstes argument nen zeiger auf das objekt kriegt, das links vom punkt stand.
abgesehen von cecaste passierte nur
anzeigeLeistung(a);
das ist ziemlich unmittelbar. in schlimmen fällen passier maximal ein
anzeigeLeistung(a+irgendEinOffset);
egal, wie tief die objekte verschachtelt sind.
also verschachteln und baen von kleinen klassen schadet nicht. verzeicgern schadet genausoviel wie in c. es gibt keinen theoretischen overhead von c++ gegenüber c.in realen programmen sieht es ein wenig anders aus, wie ich jüngst erleben, schmeißt man in c++ so viel wie möglich in boost::shared_ptrs oder wenigstens irgendwelche smart pointers. das kostet. man fasst keinen char* mehr an, sondern macht alles mit strings, das kostet. selbst die ausgabe des winzigsten integers fragt erstmal, wo der user seine tausenderpunkte haben mag, das kostst. man verwendet nur noch vector statt arrays, das kostet. insofern hat c++ in realen programmen nen nachteil. nicht nen rein theoretischen, aber man muss feststelen, daß c++-programme in manchen aspeken langsamer gebaut werden. dem gegenüber stehen die möglichkeiten, die aufgetan werden, weil man ohne roßen aufwand zugriff auf geile algos und datenstrukturen hat. also intro-sort, heaps, avl-trees und vieles mehr. das dürfte für mehr als bloß ausgleich sorgen.
aber warten wir's mal ab. wenn das so weiter geht, haben wir bald nen garbage-collector und haben nen theoretischen overhead.
-
Optimizer schrieb:
...aber vielleicht hat er sich ja über die Jahre hinweg mit C den Stil versaut??
vielleicht? da hilft nur, den cde zu lesen. ich hab mal reingelesen und weiß es nu. es war ganz deutlich.
-
Lass mich auch mal lesen du kleiner Hacker? Oder hab ich dich jetzt missverstanden
MfG SideWinder
-
Überraschen würds mich nicht. Kann ja fast gar nicht anders sein, wenn man sein Leben lang hässliche C-APIs bedient. Ob ich wohl auch berühmt wäre, wenn ich ausgiebig die WinAPI nutzen würde?
-
Optimizer schrieb:
Überraschen würds mich nicht. Kann ja fast gar nicht anders sein, wenn man sein Leben lang hässliche C-APIs bedient. Ob ich wohl auch berühmt wäre, wenn ich ausgiebig die WinAPI nutzen würde?
wenn du wie er TROTZDEM was total geiles machst, klar!
-
ACK @ volkard.
Wenn man C++ Programme so schreiben würde wie C Programme, dann hätten sie keinen Overhead, aber dafür bräuchte man dann nicht C++ sondern könnte gleich C nehmen. Das ist vermutlich der Grund dafür, warum die angesprochene Doom Engine in C geschrieben ist.
Bzgl GC - overhead gegenüber was? GC ist nicht automatisch langsamer - es ist sehr anwendungsabhängig. Siehe http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html + den ersten Link dort (Memory Allocation Costs in Large C and C++ Programs)
-
@Ringding: Wie gesagt, dein erster Absatz ist imho Mist.
MfG SideWinder
-
Ringding schrieb:
ACK @ volkard.
Wenn man C++ Programme so schreiben würde wie C Programme, dann hätten sie keinen Overhead, aber dafür bräuchte man dann nicht C++ sondern könnte gleich C nehmen. Das ist vermutlich der Grund dafür, warum die angesprochene Doom Engine in C geschrieben ist.in c++ zahlt man für die abstraktion allein keinen overhead. man kann sehr wohl erheblich weiter von der maschine abheben, ohne auch nur einen takt mehr zu zahlen.
genau deswegen müßte es gerade für engines gebot sein, c++ statt c zu nehmen. allerdings verlangt sauberes c++ vom programmierer manchmal zu viel know how, so daß man es in teams lieber nicht einsetzt.und dann ist anzugucken, was man nrmalerweise schreibt. ich schreibe grerade in c++ nen automaten, der meine html-seiten baut. eingabedaten ca. 100k text. ausgabe daten ca genausoviel text und nochmal so viel html drumherum.
laufzeit ungefähr ne sekunde.
dafür benutze ich der einfachheit halber std::string. von der sekunde laufzeit sind wahrscheinlich 90% warten af die platte. ich erstelle ja recht viele files. den rechnungsanteil könnte ich mit selbergebautem dateileser und selergebauten strings (und am besten noch nem allokator, ne hashtable wäre auch nett, nee ein trie...) wohl mehr als zehnmal so schnell machen. kann auch durchaus hundert mal so schnell werden, das passiert leicht. dann wartet mein prog leider immernoch 0.9s auf die platte und hat nu ne gesamtlaufzeit von 0.901s oder so. also spare ich mir die mühe und nehme mal string, fstream und stringstream aus std.
wenn man in c++ auf speed wert legt, sieht's für c recht schattig aus. es ist zum beispiel kein roblem, einfach mal (nachträglich!) festzustelen, daß nullterminierte stings suboptimal sind und man ieber welche mit start- und endezeiger nehmen mag, weil aufrufe von strlen() so tierisch oft vorkamen. naja, das ist schnell erledigt. in c würde es recht weh tun. man hat mehr felxibilität, die optimalen sachen rauszufinden, indem hier und da an nem schräubchen dreht und wieder mal ein detail optimiert.Bzgl GC - overhead gegenüber was? GC ist nicht automatisch langsamer - es ist sehr anwendungsabhängig. Siehe http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html + den ersten Link dort (Memory Allocation Costs in Large C and C++ Programs)
ich kann kein .ps.Z lesen.
werden da auch anwendungen wie mein html-bauer gemessen? wo es niemals auf speed ankam?konstruiere mal ne anwendung, wo ein gc speed bringt.
-
Wenn C-Programme das benötigen, was C++ bietet, dann haben sie dabei auch mindestens den gleichen Overhead... und sind doppelt so lang. Schonmal jemand virtuelle Methoden mit Funktionszeigern implementiert? *kotz*
-
Jester schrieb:
Wenn C-Programme das benötigen, was C++ bietet, dann haben sie dabei auch mindestens den gleichen Overhead... und sind doppelt so lang. Schonmal jemand virtuelle Methoden mit Funktionszeigern implementiert? *kotz*
theoretisch kann man die auch mit switch implementieren. vielleicht mir arg vielen makros?
ja, der code wird ein wenig groß. aber der code kann schneller werden, als der funktionszeigercode, weil der ganze apparat inline bleiben kann und der optimizer vollen zugriff drauf hat. funktionszeiger und virtuelle funktionen machen den optimierer leider blind an der sprungstelle.
wenn man sehr viel zeit hat und genau weiß, was man tut, kann man in der tat in c schneller sein, wenn man es mit c++ vergleicht und einem, der es nicht drauf angelegt hat, mindestens so schnell wie der mit c zu sein.
-
Ich könnte mir vorstellen, dass es (natürlich jetzt konstruiert) mit GC sehr performant wäre, in einer Schleife ständig temporäre Objekte (gerne auch unterschiedlicher Größe) zu erstellen, am Ende aber nur noch ne kleine Anzahl der Objekte zu referenzieren, bevor die Reinigung durchgeführt wird.
Das Aufsammeln von Garbage kostet nämlich nichts (wenn es keine finalizer gibt()) und es werden bei jeder Reinigung nur die referenzierten Objekte verschoben, womit der ganze Heap wieder frei wird.Ich glaub, da könnte so ne verkettete Liste schon richtig abloosen, wenn die Objekte auch noch verschieden Groß sind, das Allokieren auf nem fragmentierten Heap ist nicht das schnellste.
Jetzt zweifle ich natürlich auch nicht daran, dass du speziell für diesen Fall wieder nen schnelleren Allokator schreiben kannst.
Wer's mag. :p
-
volkard schrieb:
ich kann kein .ps.Z lesen.
werden da auch anwendungen wie mein html-bauer gemessen? wo es niemals auf speed ankam?Kind, du hörst dich nach einem erfahrenen Entwickler an, und dann das?
http://www.visotech.at/~sr/CU-CS-665-93.pdf
(leider ist das .ps mit Pixel-Font gemacht, daher schaut das so grauslich aus)Was du schreibst, stimmt schon, aber man muss halt auch einen entsprechenden Aufwand reinstecken, wenn man die Sachen wirklich schnell kriegen will. In C kommt man gar nicht erst in Versuchung, so oft malloc/free zu verwenden, weil's mühsam ist. In C++ geht alles so leicht, dass man nicht groß darüber nachdenkt.
-
Optimizer, verschieben kann man leider nichts in C/C++, weil dann die Pointer darauf ungültig würden.
-
Das ist mir schon bekannt, aber nicht mein Problem. Hat ja keiner gesagt, dass ich nen C++ GC verwenden muss. :p
Das verträgt sich sowieso überhaupt nicht mit den Pointern. Gibt ja nicht umsonst bei MS managed C++ die Referenztypen für den managed Heap.Foo^ myFoo = new Foo();
wer's mag...
-
btw, da gibt es natürlich schon Tricks. Man muss halt dann Pointer auf Pointer nehmen, dann muss man beim Verschieben nur den Pointer anpassen, der direkt auf das Objekt zeigt. Aber solange man an der Adresse rumh4x0rn kann, ist es IMHO nicht sicher, einen GC zu verwenden.
-
Ringding schrieb:
volkard schrieb:
ich kann kein .ps.Z lesen.
Kind, du hörst dich nach einem erfahrenen Entwickler an, und dann das?
http://www.visotech.at/~sr/CU-CS-665-93.pdfthx.
unten hab ich die datei schon mal. kann leider kein .pdf lesen...
naja, ich schätze, den acrobat reader zu installieren, wäre jetzt mal an der zeit.
-
Ringding schrieb:
Bzgl GC - overhead gegenüber was? GC ist nicht automatisch langsamer - es ist sehr anwendungsabhängig. Siehe http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html + den ersten Link dort (Memory Allocation Costs in Large C and C++ Programs)
ob mit oder ohne gc. die performance des verwendete allokators ist stark abhängig von der anwendung.
vorhin wurde gesagt, daß man in c viel seltener malluc/free benutzt, weils da nicht so einfach ist. richtig! das hat zur wirkung, daß man in c lieber wenige große speicherblöcke anlegt, während man in c++ gerne für jedes popelobjekt speicher anlegt (sagt so ähnlich auch alexandrescu bei seinem small object allocator in modern c++ design). das hat natürlich krasse wirkung auf den zu verwendenden allokator. für c++ sollte man auf jeden fall nen small object allocator davorspannen.
und natürlich gibts inzwishcen auch einige leute, die zwar die sprache c benutzen aber volle pulle c++-stil. und umgegehrt gibts die leute auch, die gerademal printf/malloc durch cout/new ausgetuascht haben und fleißig c in ihren c++-compiler stecken.
mit nem angemessenen small object allocator kann man schon ne ganze menge raushauen, würde ich sagen. und den kann man ja erstmal sogar abschreiben. dann kommen natürlich uch die allokatoren zum zuge, die man dazukaufen kann. sind aber immer irgendwie stangenware. sie können nicht ganz genau an die anwendung, die man hat, angepaßt werden.
die ganzen stl-container erlauben, daß man nen eigenen allokator denen mitgibt. das ist was feines. da kann man mit fast nullaufwand auch die speicherfreigaben delayen, bis der ganze container stirbt, wenn man das mag. kann ja sein, daß man mal nen relativ kurzebigen container hat. man kann von vorn herein was für die speicherlokalität tun, was kein zugekaufter universalallokator tun könnte. wegen solcher sachen kriegt man vorläufig immer einen tick mehr speed, wenn man den allokator im source zur verfügung hat.