Middle+
Koľko bajtov zaberá mapa (mapa) v Golang?
sobes.tech AI
Odpoveď od AI
Veľkosť mapy v Golangu nie je pevná a závisí od mnohých faktorov:
- Počet prvkov: Čím viac prvkov, tým viac pamäte je potrebné na ich uloženie.
- Veľkosť kľúčov a hodnôt: Každý kľúč a hodnota zaberá pamäť. Reťazce, slices, štruktúry — všetko ovplyvňuje celkovú veľkosť.
- Pomocné údaje štruktúry
hmap: mapa je ukazovateľ na štruktúruhmap. Táto štruktúra obsahuje pomocné polia:- čítač prvkov
- ukazovatele na vedrá (buckets)
- čítač migrácií (zväčšenie/zmenšenie)
- a ďalšie metadáta
- Veľkosť vedier (buckets): prvky sa ukladajú do vedier. Každé vedro má pevne stanovenú veľkosť (zvyčajne 8 párov kľúč-hodnota), ale údaje o kľúčoch a hodnotách sa ukladajú samostatne, na ktoré ukazujú ukazovatele z vedra. Vedrá môžu obsahovať nevyužitý priestor.
- Hustota zaplnenia: Pri pridávaní prvkov sa môže mapa prehashovať a zväčšiť počet vedier, čo si vyžaduje alokáciu novej pamäte.
- Zarovnanie pamäte: Go zarovnáva údaje v pamäti, čo môže viesť k ďalším bajtom na zabezpečenie správneho prístupu.
Preto nie je možné uviesť presný počet bajtov, pretože sa dynamicky mení v závislosti od obsahu a rastu mapy. Môže sa odhadnúť spodná hranica (pamäť pre hmap a prvé vedro) a horná hranica (súčet veľkostí kľúčov, hodnôt, vedier a pomocných údajov), ale presná veľkosť je určená runtime-om Go.
Na odhad veľkosti možno použiť balík unsafe alebo nástroje na ladenie, ale tie poskytnú veľkosť v konkrétnom momente pre konkrétny obsah.
// Príklad štruktúry `hmap` (zjednodušené)
// Štruktúra nie je určená na priame použitie
// a jej polia sa môžu meniť medzi verziami Go.
type hmap struct {
// Poznámka: formát `hmap` je opísaný v ../runtime/map.go.
// Ide o hash tabuľku s vedrami alokovanými z go heapu.
// hmap.buckets ukazuje na slice vedier (môže byť nil).
// Každé vedro je pole `hmap.B` s veľkosťou B.
// Pozícia v vedre ukladá kľúč a hodnotu pre jeden záznam mapy,
// plus bajt tophash. Kľúče a hodnoty sú uložené v rovnakom
// zázname vedra, pričom hodnoty nasledujú za kľúčmi.
// Ak sú veľkosti kľúčov/hodnôt veľké, zapisujú sa nepriamo do
// overflow vedier, začínajúc od overflow ukazovateľov v hlavných vedrách.
count int // počet živých buniek; nie je rovné 0, ak mapa má nejaké záznamy
flags uint8
B uint8 // log_2 počtu vedier (môže obsahovať až 2^B záznamov)
noverflow uint16 // približný počet overflow vedier
hash0 uint32 // seed hash
buckets unsafe.Pointer // pole vedier 2^B, alokované na halde
oldbuckets unsafe.Pointer // predchádzajúce pole vedier 2^B, alokované na halde
nevacuate uintptr // čítač pokroku pre evakuáciu (presun vedier do nových)
// pravda, keď typ kľúča alebo hodnoty má ukazovatele, ktoré treba skenovať
keysize uint8 // veľkosť typu kľúča
valuesize uint8 // veľkosť typu hodnoty
elemsize uint16 // veľkosť kľúča + hodnoty (pre in-place uloženie)
// ukazovateľ na slice overflow vedier, alokované na halde
overflow *[]*bmap
}
// Príklad štruktúry `bmap` (zjednodušené)
// Typ vedra.
type bmap struct {
// Rozloženie vedra je zložité.
// Podrobnosti nájdete v src/runtime/hashmap.go.
tophash [8]uint8 // 8 bajtov tophash (jeden na kv pár)
// nasledujú kľúče a potom hodnoty
// nasleduje overflow ukazovateľ
}