C ++: Performance-Einfluss von BIG-Klassen (mit viel Code)

8

Ich frage mich, ob und wie das Schreiben von "allmächtigen" Klassen in C ++ tatsächlich die Leistung beeinflusst.

Wenn ich zum Beispiel eine Klasse Punkt mit nur uint x; uint y; als Daten und haben praktisch alles definiert, was Mathematik als Methode bis zu einem bestimmten Punkt tun kann. Einige dieser Methoden könnten sehr umfangreich sein. (Kopier-) Konstruktoren tun nichts weiter als die Initialisierung der beiden Datenelemente.

%Vor%

Jetzt. Ich lade ein großes Bild und erstelle einen Punkt für jedes Pixel, stop em in einen Vektor und benutze sie. (Sagen wir, alle Methoden werden einmal aufgerufen) Dies ist nur als ein dummes Beispiel gemeint!

Wäre es langsamer als die gleiche Klasse ohne die Methoden, aber mit vielen Utility-Funktionen? Ich rede nicht über virtuelle Funktionen in irgendeiner Weise!

Meine Motivation dafür: Ich finde oft, dass ich nette und relativ starke Klassen schreibe, aber wenn ich eine Menge wie im obigen Beispiel initialisieren / verwenden muss, werde ich nervös. Ich denke, ich sollte nicht.

Was ich zu wissen glaube ist:

  1. Methoden existieren nur einmal im Speicher. (Optimierungen beiseite)
  2. Zuweisung findet nur für die Daten statt Mitglieder, und sie sind das einzige Ding kopiert.

Es sollte also nichts ausmachen. Fehle ich etwas?

    
AndreasT 15.09.2009, 08:35
quelle

9 Antworten

10

Sie haben Recht, Methoden existieren nur einmal im Speicher, sie sind wie normale Funktionen, wobei ein zusätzlicher Parameter versteckt ist.

Und natürlich werden nur Datenmitglieder für die Zuweisung berücksichtigt, gut, die Vererbung kann einige zusätzliche ptrs für vptrs in der Objektgröße einführen, aber keine große Sache

    
Arkaitz Jimenez 15.09.2009, 08:37
quelle
6

Sie haben schon einige ziemlich gute technische Ratschläge. Ich möchte etwas Nicht-Technisches einbringen: Da die STL uns alle gezeigt hat, ist es vielleicht nicht die beste Art, dies zu tun. Anstatt Argumente zu häufen, verweise ich auf den Artikel von Scott Meyers zum Thema: Wie Nichtmitgliedsfunktionen die Kapselung verbessern .

Obwohl es technisch gesehen kein Problem geben sollte, möchten Sie vielleicht dennoch Ihr Design von einem Design-POV überprüfen.

    
sbi 15.09.2009 09:29
quelle
3

Ich nehme an, das ist mehr eine Antwort als Sie suchen, aber hier geht ...

SO ist mit Fragen gefüllt, bei denen sich die Leute Sorgen um die Leistung von X, Y oder Z machen, und diese Sorge ist eine Form von raten .

Wenn Sie sich Sorgen um die Leistung von etwas machen, machen Sie sich keine Sorgen, finden Sie heraus .

Hier ist was zu tun:

  1. Schreiben Sie das Programm

  2. Leistung optimieren

    >
  3. Lerne aus der Erfahrung

Was mir das beigebracht hat, und ich habe es immer und immer wieder gesehen, ist folgendes:

  • Best Practice sagt Nicht zu früh optimieren .

  • Best Practice sagt, dass Do viele Datenstrukturklassen mit mehreren Abstraktionsebenen und die besten Big-O-Algorithmen, "Information Hiding", mit ereignisgesteuerten und Benachrichtigungs- Stil Architektur.

  • Performance Tuning verrät, wohin die Zeit geht, nämlich: Galoppierende Allgemeingültigkeit, Berge aus Maulwurfshügeln machen, Funktionen aufrufen & amp; Eigenschaften, ohne zu wissen, wie lange sie brauchen, und dies über mehrere Schichten mit exponentieller Zeit.

  • Dann stellt sich die Frage: Was ist der Grund für die Best-Practice für die Big-O-Algorithmen, die Event- und Notification-Driven-Architektur etc. Die Antwort lautet: Nun, unter anderem Leistung .

In gewisser Weise sagen uns Best Practices: vorzeitig optimieren . Holen Sie den Punkt? Es heißt "mach dir keine Sorgen über die Leistung", und es heißt "Sorge um die Leistung", und es verursacht genau das, was wir erfolglos versuchen, uns nicht zu sorgen. Und je mehr wir uns darüber Sorgen machen, desto schlimmer wird es, je besser wir es beurteilen.

Mein konstruktiver Vorschlag lautet wie folgt: Befolgen Sie die obigen Schritte 1, 2 und 3. Das wird dir beibringen, wie man Best Practice in der Moderation einsetzt, und das wird dir das beste Allround-Design geben.

    
Mike Dunlavey 15.09.2009 12:26
quelle
1

Wenn Sie wirklich besorgt sind, können Sie Ihrem Compiler sagen, dass er die Konstruktoren inline einbinden soll. Dieser Optimierungsschritt sollte Sie mit sauberem Code und sauberer Ausführung belassen.

    
carl 15.09.2009 08:39
quelle
1

Diese 2 Bits Code sind identisch:

%Vor%

vorausgesetzt, dass die Klasse Point eine nicht-virtuelle Methode getLength () hat. Der erste Aufruf ruft tatsächlich int getLength(Point &this) auf, eine identische Signatur wie die, die wir in unserem zweiten Beispiel geschrieben haben. (*)

Dies würde natürlich nicht gelten, wenn die Methoden, die Sie aufrufen, virtuell sind, da alles eine zusätzliche Ebene der Indirektion durchlaufen würde (etwas, das dem C-Stil int l=x->lpvtbl->getLength(x) ähnlich ist), ganz zu schweigen von dem statt 2 int für jedes Pixel, das Sie tatsächlich 3 haben, das Extra ist der Zeiger auf den virtuellen Tisch.

(*) Das ist nicht genau richtig, der "This" -Zeiger wird durch eines der CPU-Register statt durch den Stapel geleitet, aber der Mechanismus hätte auf jede Art und Weise funktionieren können.

    
Blindy 15.09.2009 08:45
quelle
1

Erstens: nicht zu früh optimieren. Zweitens: Sauberer Code ist einfacher zu pflegen als optimierter Code.

Methoden für Klassen haben diesen versteckten Zeiger, aber Sie sollten sich nicht darum kümmern. Die meiste Zeit versucht der Compiler, es über Register zu übergeben.

Vererbung und virtuelle Funktion führen Umleitungen in den entsprechenden Aufrufen ein (Vererbung = Konstruktor / Destruktoraufruf, virtuelle Funktion - jeder Funktionsaufruf dieser Funktion).

Kurz:

  • Objekte, die Sie nicht erstellen / zerstören, können oft virtuelle Methoden, Vererbung usw. haben, solange dies dem Design zu Gute kommt.
  • Objekte, die Sie häufig erstellen / löschen, sollten klein sein (wenige Datenelemente) und sollten nicht viele virtuelle Methoden haben (am besten wäre überhaupt keine - leistungsmäßig).
  • versuche, kleine Methoden / Konstruktoren zu inline zu schreiben. Dies reduziert den Overhead.
  • Gehen Sie für ein sauberes Design und Refactoring, wenn Sie nicht die gewünschte Leistung erreichen.

Es gibt eine andere Diskussion über Klassen mit großen oder kleinen Schnittstellen (zum Beispiel in einem von Scott Meyers (More) Effective C ++ Books - er entscheidet sich für minimale Schnittstelle). Aber das hat nichts mit Leistung zu tun.

    
Tobias Langner 15.09.2009 08:45
quelle
0

Ich stimme den obigen Kommentaren bezüglich Leistung und Klassenlayout zu und möchte einen Kommentar hinzufügen, der noch nicht zum Thema design erwähnt wurde.

Es fühlt sich für mich so an, als würden Sie Ihre Point-Klasse über ihren eigentlichen Design-Bereich hinaus verwenden. Sicher, es kann so verwendet werden, aber sollte es?

In der Vergangenheit war ich oft mit ähnlichen Situationen konfrontiert, und in der Regel war das beste Endergebnis, wenn ich bei der spezialisierten Verarbeitung (zB Bildverarbeitung) einen speziellen Code für die auf unterschiedlich Aus Puffer war effizienter.

Dies ermöglicht Ihnen auch, die Performance für den wichtigen Fall auf eine sauberere Weise zu optimieren, ohne dass der Basiscode weniger wartbar wird.

In der Theorie bin ich mir sicher, dass es eine schlaue Art gibt, eine komplexe Kombination aus Template-Code, konkretem Klassen-Design usw. zu verwenden und fast die gleiche Laufzeit-Effizienz zu erreichen ... aber das will ich normalerweise nicht Machen Sie die Komplexität der Implementierung Handel.

    
ted_j 15.09.2009 12:25
quelle
0

Elementfunktionen werden nicht zusammen mit dem Objekt kopiert. Nur Datenfelder tragen zur Größe des Objekts bei.

    
Matt Fichman 16.09.2009 06:31
quelle
0

Ich habe dieselbe Punktklasse wie Sie erstellt, außer dass es eine Vorlagenklasse ist und alle Funktionen inline sind. Ich erwarte, dass die Leistungssteigerung nicht abnehmen wird. Ein Bild der Größe 800x600 hat jedoch 480k pixels und sein Speicherdruck wird nahe an 4M ohne Farbinformationen sein. Nicht nur der Speicher, sondern auch die Initialisierung von 480k object wird zu viel Zeit in Anspruch nehmen. Daher denke ich, dass es in diesem Fall keine gute Idee ist. Wenn Sie diese Klasse jedoch verwenden, um die Position eines Bildes zu transformieren, oder verwenden Sie sie für grafische Grundelemente (Linien, Kurven, Kreise usw.)

    
Cem Kalyoncu 15.09.2009 09:46
quelle

Tags und Links