Heim >Backend-Entwicklung >Golang >Optimieren von C-Struktur-Layouts

Optimieren von C-Struktur-Layouts

DDD
DDDOriginal
2025-01-03 13:57:391005Durchsuche

Betrachten wir eine einfache Struktur:

struct foo {
    const char * str;
    unsigned char flag;
    uint64_t len;
};

Angenommen, dieser Code wird als Teil eines Programms ausgeführt, das auf einem 64-Bit-Computer ausgeführt wird: Welches Ergebnis würden Sie von sizeof(struct foo) erwarten?

Die meisten Leute, die sich nie mit Strukturgrößen und Optimierungen herumschlagen mussten, würden vermuten, dass es 17 sein sollte...

... aber es sind 24! Warum ist das so?

Der Grund für dieses Verhalten liegt darin, dass Compiler Strukturlayouts auf Geschwindigkeit optimieren und es die moderne Norm ist, dass ausgerichtete Speicherzugriffe der schnellste Weg sind, auf Daten zuzugreifen.

Das bedeutet, dass Ihre Daten je nach Feldtyp und CPU eine gewisse Ausrichtung haben und so positioniert werden, dass diese Ausrichtung berücksichtigt wird (oder so, dass Feldadresse % Feldausrichtung == 0).

Größe, Ausrichtung, Polsterung

Im Fall des vorherigen Beispiels sind Zeiger und 64-Bit-Felder auf 64-Bit-Maschinen 8B-ausgerichtet. Das bedeutet, dass der Compiler einige generieren wird, um ein Layout zu erzwingen, bei dem alles in der Struktur ausgerichtet ist Abstand zwischen den Feldern flag und len:

optimizing c structs layouts

Betrachten wir nun ein weiteres Beispiel, in dem eine Struktur wie diese auf demselben Computer wie zuvor definiert wird:

struct bar {
    const char * str;
    short s1;
    int i1
    short s2;
    int i2;
};

Wie berechnen wir seine Größe?

Es gibt drei Regeln:

  • Strukturfelder möchten an ihrer eigenen natürlichen Ausrichtung ausgerichtet sein.
  • Die gesamte Strukturausrichtung entspricht der Ausrichtung ihres breitesten Feldes
  • Wenn Sie zwei Strukturen desselben Typs nebeneinander platzieren müssten, sollte die zweite Struktur an ihrer Ausrichtung ausgerichtet sein – das bedeutet, dass Strukturen bis zu ihrer Ausrichtung eine abschließende Auffüllung haben müssen

Kurze Zusammenfassung der grundlegenden Typausrichtung und -größe für 64-Bit-Maschinen:

type size alignment
char 1 1
short 2 2
int 4 4
long 8 8
float 4 4
double 8 8
pointers 8 8

Denken Sie auch daran:

  • Arrays haben die Ausrichtung ihres Werttyps und eine Größe, die sizeof(type) * Elementanzahl ist.
  • Gewerkschaften haben die Ausrichtung und Größe ihres breitesten Mitglieds.

Und Sie können die äußerst nützlichen Operatoren sizeof und _Alignof verwenden, um diese Informationen für Ihre benutzerdefinierten Typen abzurufen. Beachten Sie, dass _Alignof ab C11 verfügbar ist und ab C23 alignof heißt. Es stimmte immer mit dem überein, was ich in C verstehe, seit C 11.

Für weitere Informationen: Die Bibel zu diesem Thema ist „The Lost Art of Structure Packing“, aus der ich fast alles gelernt habe, was ich darüber weiß, zusammen mit viel Übung und praktischer Erfahrung.

Optimierung Ihrer Strukturen: Stropt

Dieses Thema kommt bei der Arbeit ziemlich häufig zur Sprache, wo das Einsparen von Bytes hier und da sehr wichtig ist, wenn große Datenmengen kontinuierlich in Warteschlangen gesendet werden und so weiter.

Um mir das Leben zu erleichtern, habe ich ein Tool geschrieben, das einige Statistiken zu einem Typ erstellt, den Sie als Eingabe übergeben, unter Bezugnahme auf eine Quelldatei oder einen Codeausschnitt. Es heißt stropt (Strukturoptimierer).

Abathargh/stropt auf GitHub

bauen und installieren

Wenn Sie über eine lokale Go-Installation verfügen, können Sie die Anwendung direkt erstellen oder installieren:

struct foo {
    const char * str;
    unsigned char flag;
    uint64_t len;
};

Bereits kompilierte Binärdateien für eine Liste von OS/Archs-Kombinationen werden auch auf der Github-Release-Seite bereitgestellt:

Stropt-Binärdateien

Verwendung des Tools

Sie können entweder stropt verwenden, indem Sie die zu analysierende Quelle als Zeichenfolge übergeben:

struct bar {
    const char * str;
    short s1;
    int i1
    short s2;
    int i2;
};

optimizing c structs layouts

Oder Sie können eine Datei übergeben, in der die Definition enthalten ist:

git clone https://github.com/Abathargh/stropt
go build

// or, if you want to install this directly
go install github.com/Abathargh/stropt

optimizing c structs layouts

Das Tool kann auch eine mögliche Optimierung für Ihre Typen bereitstellen, indem es das Flag -optimize verwendet, und es erkennt Felder, die selbst Strukturen sind:

optimizing c structs layouts

Beachten Sie, dass das Verbose-Flag verwendet wird, um innere Strukturen (und Vereinigungen) zusammen mit ihrer Feldausrichtung und -größe anzuzeigen.

was kommt als nächstes

Dieses Tool wurde in go unter Verwendung des großartigen C-Compiler-Frontends modernc.org/cc zum Parsen von C-Code und Lipgloss von Charmbracelet für die Benutzeroberfläche geschrieben.

Ich schreibe dies für mich selbst, teile es aber gerne öffentlich. Ich würde dies gerne zu einer Webanwendung machen, damit sie einfacher direkt in einem Browser verwendet werden kann, also ist das wahrscheinlich das nächste, woran ich arbeiten werde!

Das obige ist der detaillierte Inhalt vonOptimieren von C-Struktur-Layouts. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn