Die Optimierung der Datenanordnung im Speicher ist ein Schlüsselmerkmal von Rust, das es ermöglicht, Ressourcen zu sparen, ohne die Sicherheit des Codes zu beeinträchtigen. Enum Layout beschreibt, wie der Compiler die Varianten von Enums (mit strukturierten oder primitiven Varianten) sowie die Felder jeder Struktur anordnet. In anderen Sprachen ist eine solche Optimierung oft verborgen, während es in Rust sehr wichtig ist, die Reihenfolge der Felder zu berücksichtigen, um übermäßigen Speicherverbrauch zu vermeiden.
Wenn die Reihenfolge der Felder in einer Struktur ungünstig gewählt wird, kann die Struktur aufgrund der Datenanpassungsanforderungen "aufgebläht" werden. Bei Enums mit assoziierten Daten ist die Situation komplizierter – die Größe des Enums wird durch die größte Variante plus die Größe des Diskriminators bestimmt. Ignoriert man dies, führt das zu übermäßigem Speicherverbrauch und einer Verringerung der Cache-Leistung des Prozessors.
Um Strukturen und Enums effizient zu packen, sollte man zuerst die "breitesten" Felder anordnen, dann die schmaleren, und die möglichen Padding Bytes berücksichtigen, die der Compiler hinzufügen könnte. Bei Enums sollte man die Struktur der Varianten so wählen, dass sie nicht unnötig auf die maximale Größe streben, wenn dies nicht gerechtfertigt ist.
Beispielcode:
struct BadAlign { a: u8, b: u32, c: u16, } struct GoodAlign { b: u32, c: u16, a: u8, } enum Packet { A(u8), B(u32, [u8; 10]), }
Wichtige Merkmale:
Kann man eine Struktur kleiner machen, indem man einfach die Reihenfolge der Felder ändert?
Ja. Wenn die Felder in absteigender Reihenfolge der Größe angeordnet sind, verringert der Compiler oft die Anzahl der Paddings, wodurch die Gesamtgröße der Struktur reduziert wird.
println!("{}", std::mem::size_of::<BadAlign>()); // beispielsweise 12 println!("{}", std::mem::size_of::<GoodAlign>()); // beispielsweise 8
Beeinflusst eine bestimmte Reihenfolge der Felder die Zugriffsleistung?
Die Reihenfolge selbst beeinflusst nicht die Zugriffszeit über die Felder. Bei einer sequenziellen Durchlaufstruktur auf niedriger Ebene (z. B. mit SIMD-Anweisungen oder bei der Arbeit mit Arrays von Strukturen in einer Schleife) beschleunigt die richtige Ausrichtung den Zugriff durch eine bessere Nutzung des Caches.
Wenn eine Variante des Enums sehr groß ist, wird jede Instanz des Enums genauso viel Speicher benötigen, auch wenn sie andere Varianten hat?
Ja, die Größe des Enums wird immer durch die größte Variante plus den Diskriminator bestimmt. Jedes Packet benötigt die Größe von B, selbst wenn es A enthält.
** Negativer Fall
In der Struktur stehen die Felder u8, dann u64. Die Verwendung in einem Array von 100000 Einträgen verbraucht bis zu einem Gigabyte Speicher aufgrund von Padding.
Vorteile:
Nachteile:
** Positiver Fall
Strukturen wurden nach der Breite der Felder sortiert, große Varianten des Enums wurden in Box ausgegliedert, kleine blieben im Platz.
Vorteile:
Nachteile: