Was kostest eigentlich:
-
1.) Abstrakte Klassen
class foo{ int einInt; public: void bar()=0; };
Ich habe schon gehört, daß virtuelle Funktionen einen Eintrag in der vtbl haben müssen, damit der Compiler diese auflösen kann.
Allerdings sind abstrakte Basisklassen oftmals ein muss für gutes Design. Was kosten virtuelle Funktionen und in welchen Fällen kann der Compiler diesen Overhead vermeiden?
2.) Exceptions
Ich habe schon öft gehört das Exceptions und try/catch Blöcke auch "teuer" sein sollen. Nun würden mich dafür die Gründe interessieren. Auf der einen Seite hört man, daß man eine Fehlerbehandlung im C-Stil per Rückgabewert vermeiden sollte, andererseits hört man das Exceptions "teuer" sind.
Wie sieht es in real großen Projekten aus?
Danke
-
Der Zeiger auf die VFT (virtuelle Funktionstabelle) braucht i.d.R. 4 Extra-Bytes (normalerweise am Anfang eines Objektes). Die VFT selbst wird vom Linker erzeugt und ist statisch.
Der Funktionsaufrufsoverhead haengt vom Compiler ab. I.d.R. kommen zwei Extra-Befehle hinzu (laden der VFT in ein Register, Lesen des n-ten Eintrags).
Fuer Exceptions kommt wesentlich mehr hinzu, was genau, haengt auch vom Compiler ab. I.d.R. wird beim Funktionsaufruf ein Extra-Frame-Pointer fuer Exceptions mit uebergeben, damit beim Auftreten einer Exception der passende Handler gesucht werden kann. Je nach Schachtelungstiefe zwischen try und throw werden dementsprechend viele Speicherzugriffe benoetigt. Dies duerfte in der Realitaet allerdings kaum eine Rolle spielen, da Exceptions ja "Ausnahmen" sein sollen.
Alles in allem sollte man virtuelle Methoden und Exceptions dort benutzen wo es Sinn macht. Ausserdem sollte man die STL verwenden, wo es geht, da ein optimierender Compiler daraus sehr guten Code machen kann.
Templates (wie von der STL verwendet), blaehen den Code zwar auf, verkuerzen aber die Entwicklungszeit dramatisch. Auf die Performance haben sie eher geringe Auswirkung. Jedoch kann es sich manchmal lohnen, eigene Klassen zu entwickeln, wenn die STL konzeptionell bedingt zu langsam ist.
-
Hi,
den Overhead von virtuellen Methoden kannst du in 99,9% aller Fälle vernachlässigen, weil er nur einige Ticks kostet und so im Vergleich zum eigentlichen Funktionsaufruf (und natürlich der Funktion selbst) nicht ins Gewicht fällt. Wegoptimieren kann der Compiler einen virtuellen Aufruf allerdings nicht.
Der Exception-Overhead ist da schon größer, weil ja der Stack aufgerollt werden muss und alle Objekte zerstört werden müssen. Aber auch das fällt nicht ins Gewicht, weil du Exceptions ja im Normalfall sowieso nicht wirfst, deswegen heißen sie ja Exceptions.
Zu beachten ist allerdings, dass Exceptions auch wenn sie nicht geworfen werden, etwas Overhead mit sich bringen, wenn du Exceptions garantiert nicht verwendest, kannst du diesen Overhead-Code mit einem Compilerschalter deaktivieren.
ChrisM
-
Power Off schrieb:
Fuer Exceptions kommt wesentlich mehr hinzu, was genau, haengt auch vom Compiler ab. I.d.R. wird beim Funktionsaufruf ein Extra-Frame-Pointer fuer Exceptions mit uebergeben, damit beim Auftreten einer Exception der passende Handler gesucht werden kann. Je nach Schachtelungstiefe zwischen try und throw werden dementsprechend viele Speicherzugriffe benoetigt.
bestimmt ist das auch davon abhängig wie das betriebssystem exceptions unterstützt. z.b. hat windoofs (die nt-abkömmlinge jedenfalls) schon eingebautes exception-handling und das könnte sich so'n compiler teilweise zu nutze machen
-
Stimmt, aber es kostet trotzdem Zeit.
Wenn man alle Klassen zur Compilezeit kennen würde, könnte man auch overhead-freien Exception-Code erzeugen, aber das ist leider nicht möglich, weil C++ auf dem Prinzip der Übersetzungseinheiten aufgebaut ist.
-
Danke an alle!
Wir sollte man im Regelfall eine Fehlerbehandlung vornehmen?
Nehmen wir als Beispiel File IO:
- Benutzer versucht Datei zu öffen, existiert aber nicht
- Benutzer versucht in Datei zu öffnen, keine Rechte
- Benutzer versucht in Datei zu schreiben, keine RechteWürdet ihr dafür Exceptions nehmen, oder doch lieber C-like mit Errorcodes?
-
Kann man schon Exceptions nehmen dafuer. Dies erspart dem Programmierer, im Regelfall Ruecksicht darauf zu nehmen.
Am besten ist, man faengt Exceptions moeglichst weit oben ab, also z.B. in einem Programmteil, der zuerst eine Dialogbox zur Dateiauswahl oeffnet und dann die Datei oeffnet, koennte man das Oeffnen der Datei in einen try ... catch - Block kapseln, und im catch-Block eine MessageBox mit ner Fehlermeldung anzeigen, um dann erneut die Dialogbox zur Dateiauswahl anzuzeigen, oder sowas.
(EDIT: Wichtiger Hinweis: Natuerlich muss man beim Arbeiten mit Exceptions darauf achten, dass das Stack-Unwinding / der Rollback sauber funktioniert. Man darf also den new-Operator nur dann verwenden, wenn man im Fall einer Exception auch wieder sauber aufraeumt)