Middle+
Wie viele Bytes benötigt eine Karte (Map) in Golang?
sobes.tech KI
Antwort von AI
Die Größe der Map in Golang ist nicht fest und hängt von vielen Faktoren ab:
- Anzahl der Elemente: Je mehr Elemente, desto mehr Speicher wird für deren Speicherung benötigt.
- Größe der Schlüssel und Werte: Jeder Schlüssel und Wert belegt Speicher. Strings, Slices, Strukturen – all dies beeinflusst die Gesamtsgröße.
- Servicedaten der Struktur
hmap: eine Map ist ein Zeiger auf die Strukturhmap. Diese Struktur enthält Servicefelder:- Zähler der Elemente
- Zeiger auf die Buckets
- Zähler der Migrationen (Wachsen/Schrumpfen)
- und andere Metadaten
- Größe der Buckets: Elemente werden in Buckets gespeichert. Jeder Bucket hat eine feste Größe (normalerweise 8 Schlüssel-Wert-Paare), aber die Daten der Schlüssel und Werte werden separat gespeichert, auf die die Zeiger in den Buckets verweisen. Buckets können ungenutzten Raum enthalten.
- Füllgrad: Beim Hinzufügen von Elementen kann die Map neu gehasht werden und die Anzahl der Buckets erhöht werden, was die Zuweisung neuen Speichers erfordert.
- Speicheralignment: Go richtet die Daten im Speicher aus, was zu zusätzlichen Bytes führen kann, um einen korrekten Zugriff zu gewährleisten.
Daher ist es unmöglich, eine genaue Byte-Anzahl anzugeben, da sie sich dynamisch ändert, abhängig vom Inhalt und Wachstum der Map. Es kann eine untere Grenze (Speicher für hmap und den ersten Bucket) und eine obere Grenze (Summe der Größen der Schlüssel, Werte, Buckets und Metadaten) geschätzt werden, aber die genaue Größe wird vom Go-Runtime bestimmt.
Zur Schätzung der Größe kann das Paket unsafe oder Debugging-Tools verwendet werden, aber sie geben die Größe zu einem bestimmten Zeitpunkt für einen bestimmten Inhalt an.
// Beispiel für eine vereinfachte hmap-Struktur
// Die Struktur ist nicht für den direkten Gebrauch bestimmt
// und ihre Felder können zwischen Go-Versionen variieren.
type hmap struct {
// Das Format des hmap ist in ../runtime/map.go beschrieben.
// Es ist eine Hashtabelle mit Buckets, die aus dem Go-Heap alloziert werden.
// hmap.buckets zeigt auf das Slice der Buckets (kann nil sein).
// Jeder Bucket ist ein Array von hmap.B entries, wobei B die Bucket-Größe ist.
// Ein Bucket-Eintrag speichert den Schlüssel und den Wert für einen einzelnen Map-Eintrag,
// plus ein tophash-Byte. Schlüssel und Werte werden im selben
// Bucket-Eintrag gespeichert, wobei die Werte den Schlüsseln folgen.
// Wenn Schlüssel-/Wertgrößen groß sind, werden sie indirekt in
// Overflow-Buckets geschrieben, beginnend mit Overflow-Pointern in den
// Haupt-Buckets.
count int // Anzahl der lebenden Zellen; ist != 0, wenn Map Einträge hat
flags uint8
B uint8 // log_2 der Anzahl der Buckets (kann bis zu 2^B Einträge enthalten)
noverflow uint16 // ungefähre Anzahl der Overflow-Buckets
hash0 uint32 // Hash-Seed
buckets unsafe.Pointer // Array von 2^B Buckets, im Heap alloziert
oldbuckets unsafe.Pointer // vorheriges Array von 2^B Buckets, im Heap alloziert
nevacuate uintptr // Fortschrittszähler für Evakuierung (Buckets verschoben in den neuen)
// Wahr, wenn Schlüssel- oder Werttyp Zeiger enthält, die gescannt werden müssen
keysize uint8 // Größe des Schlüsseltyps
valuesize uint8 // Größe des Werttyps
elemsize uint16 // Größe von Schlüssel + Wert (für In-Place-Speicherung)
// Zeiger auf eine Slice von Overflow-Buckets, im Heap alloziert
overflow *[]*bmap
}
// Beispiel für eine vereinfachte bmap-Struktur
// Bucket-Typ.
type bmap struct {
// Das Layout eines Buckets ist komplex.
// Siehe src/runtime/hashmap.go für Details.
tophash [8]uint8 // 8 tophash Bytes (ein pro Schlüssel-Wert-Paar)
// gefolgt von Schlüsseln und dann Werten
// gefolgt von einem Overflow-Pointer
}