C++ Performancefrage zu call by reference einer Struktur

T_55

Lieutenant
Registriert
Feb. 2013
Beiträge
638
Hallo,

mal eine Basisfrage zur Performance bei einer call by reference Übergabe an eine Funktion.
Ist es performancemäßig egal ob in einem Struct 100 oder nur 2 Datentypen enthalten sind wenn das Struct per Referenz an eine Funktion übergeben wird? Wenn ich es richtig verstanden habe müsste doch nur die Speicheradresse des Structs übergeben werden, daher sollte es immer gleich performant sein, richtig oder falsch?

Meine Gedanke dazu: Wenn einer Funktion sehr viele Variablen übergeben werden müssen, davon aber die meißten eher selten in der Funktion genutzt werden, wäre es dann nicht besser statt etlicher Funtionsparameter einfach ein Struct zu übergeben was die Variablen beinhaltet?

Gruß
 
Ist es performancemäßig egal ob in einem Struct 100 oder nur 2 Datentypen enthalten sind wenn das Struct per Referenz an eine Funktion übergeben wird? Wenn ich es richtig verstanden habe müsste doch nur die Speicheradresse des Structs übergeben werden, daher sollte es immer gleich performant sein, richtig oder falsch?
Für das übergeben an sich ja. Für das Caching der Struct selbst nein.

Meine Gedanke dazu: Wenn einer Funktion sehr viele Variablen übergeben werden müssen, davon aber die meißten eher selten in der Funktion genutzt werden, wäre es dann nicht besser statt etlicher Funtionsparameter einfach ein Struct zu übergeben was die Variablen beinhaltet?
Die allermeisten Funktionsaufrufe in vernünftigen Programmen haben doch in der Regel weniger als 10 Parameter: Ein paar Objekte und ein paar primitive Variablen das wars; wenn sie deutlich mehr haben, dann läuft irgendetwas ziemlich falsch. Zudem werden die allermeisten Funktionsaufrufe sowieso vom Compiler geinlint (zumindest wenn ein Programmierer sein Programm richtig gestaltet). Dieses Inlining entfernt nicht nur den kompletten Overhead des Funktionsaufrufes, was diese Überlegungen für die Reduktion des Overheads überflüssig macht, sondern ermöglicht auch weiterreichende Compileroptimierungen. Deshalb lohnt es sich m.E. nicht, sich für diese paar byte Kopieroperationen, die bei den nicht geinlinten Funktionen so anfallen, den Kopf zu zerbrechen, wie man sie optimieren könnte. Denn meist gibt es viel größere Performanceprobleme in einem Programm.
 
Zuletzt bearbeitet:
Guten Morgen!

T_55 schrieb:
wäre es dann nicht besser statt etlicher Funtionsparameter einfach ein Struct zu übergeben was die Variablen beinhaltet?

Das ist eine Frage von Dir im Kontext von C++, also einer objektorientierten Programmiersprache. Du beschreibst Dein Problem aus Sicht der prozeduralen Programmierung (und nutzt auch die Begriffe dafür). Nutze die Objektorientierung! Zur Lösung Deines Problems nimmst Du eine Klasse dafür, die Du dann per Reference übergibst.
 
@T_55: Stimme Nai vollkommen zu (auch wenn inlining meiner Erfahrung nach wesentlich seltener passiert als man denkt). Darüber hinaus müsstest du die Parameter ja auch erstmal in ner Struktur sammeln. Wenn diese ohnehin logisch zusammengehören (z.B. x und y Koordinate eines Punktes) sollten sie ohnehin in einer gemeinsamen Datenstruktur gespeichert sein. Wenns aber eigentlich unabhängige Daten sind, dann sparst du dir vielleicht was beim Funktionsaufruf, aber hast dafür den Overhead beim Zusammenkopierern der Elemente (was potentiell wesentlich teurer ist).
So oder so reden wir hier von absoluten Microoptimierungen. In 99% der Fälle wirst du keinen Unterschied feststellen.
 
Danke euch für die Antworten! Da die Variablen thematisch schon zusammengehören denke ich werde ich es in ein Struct packen. Der Vorteil ist auch, dass das Struct einfach weniger Schreibarbeit ist wenn die Referenz ggf an noch weitere Unterfunktionen weitergegebnen wird, da spart man einfach an Anzahl von Funtionsparametern.

Rein aus Interesse, ich hab von Caching keine Ahnung aber wenn das Caching einer Struktur mit steigender Anzahl von integrierten Variablen schlechter wird, müsste das dann doch auch für globale Variablen gelten oder? Denn dann könnte man doch sagen, man verlagert das Problem (größere Anzahl von Variablen im Struct) nur an einen anderen Ort.

Gruß
 
Ich stehe witzigerweise gerade for exakt demselben "Problem" - einen Haufen Methoden in verschiedenen Klassen, die Dinge tun, die relativ wenig miteinander zu tun haben, aber denselben Haufen Kontextinformationen benötigen, die sich allerdings auch innerhalb der Aufrufe nie ändern. Da wird dann so ein Struct durch die Gegend geschoben:

Code:
  struct WinInfo {
    WinInfo(...);  // Bla
    
    TileType winningTile;
    
    TileType jikaze;
    TileType bakaze;
    
    WinMode    winMode;
    WinTurn    winTurn;
    HandMode   handMode;
    RiichiMode riichiMode;
  };

Allerdings ist das in meinen Augen eher eine Stilfrage und keine, bei der es großartig um Performance gehen sollte. idealerweise gruppiert man Daten, die zusammen gehören, ohnehin irgendwie - aber um ehrlich zu sein, sehe ich in so einem Fall keine praktikable Alternative dazu.
 
Rein aus Interesse, ich hab von Caching keine Ahnung aber wenn das Caching einer Struktur mit steigender Anzahl von integrierten Variablen schlechter wird, müsste das dann doch auch für globale Variablen gelten oder? Denn dann könnte man doch sagen, man verlagert das Problem (größere Anzahl von Variablen im Struct) nur an einen anderen Ort.

Defakto werden die Performanceunterschiede hier auch durch das Caching komplet vernachlässigbar sein. Aber in der Regel verwendest du ja als "Alternative" zu einer Struct primitive automatische Variablen und keine primitive globalen Variablen. Primitive automatische Variablen kann der Compiler idr gut optimieren und dadurch das Workingset reduzieren. Dahingegen ist das Speicherlayout einer Struct (abgesehen von automatischen Structs in manchen Fällen) fest. Wenn du primitive globale Variablen als Alternative wählst, so kommt erschwerend hinzu, dass diese irgendwie im Datensegment verstreut vorliegen können und dementsprechend sich die Lokalität deiner Speicherzugriffe und damit das Caching verschlechtert.
 
Zurück
Oben