Middle+
Kolik bajtů zabírá mapa (mapa) v Golang?
sobes.tech AI
Odpověď od AI
Velikost mapy v Golangu není pevná a závisí na mnoha faktorech:
- Počet prvků: Čím více prvků, tím více paměti je potřeba pro jejich uložení.
- Velikost klíčů a hodnot: Každý klíč a hodnota zabírá paměť. Řetězce, slices, struktury — to vše ovlivňuje celkovou velikost.
- Pomocná data struktury
hmap: map je ukazatel na strukturuhmap. Tato struktura obsahuje pomocná pole:- čítač prvků
- ukazatele na koše (buckets)
- čítač migrací (zvětšení/zmenšení)
- a další metadata
- Velikost košů (buckets): prvky jsou uloženy v koších. Každý koš má pevnou velikost (obvykle 8 párů klíč-hodnota), ale data klíčů a hodnot jsou uložena samostatně, na které ukazují ukazatele z koše. Koše mohou obsahovat nevyužitý prostor.
- Hustota zaplnění: Při přidávání prvků se může map přehashovat a zvětšovat počet košů, což vyžaduje alokaci nové paměti.
- Zarovnání paměti: Go zarovnává data v paměti, což může vést k přídavným bajtům pro zajištění správného přístupu.
Nelze přesně určit počet bajtů, protože se dynamicky mění v závislosti na obsahu a růstu mapy. Lze odhadnout spodní hranici (paměť pro hmap a první koš) a horní hranici (součet velikostí klíčů, hodnot, košů a pomocných dat), ale přesná velikost je určena runtime Go.
Pro odhad velikosti lze použít balíček unsafe nebo ladicí nástroje, ale ty poskytnou velikost v konkrétním okamžiku pro konkrétní obsah.
// Příklad struktury `hmap` (zjednodušený)
// Struktura není určena pro přímé použití
// a její pole se mohou měnit mezi verzemi Go.
type hmap struct {
// Poznámka: formát `hmap` je popsán v ../runtime/map.go.
// Je to hash tabulka s koši alokovanými z go heapu.
// hmap.buckets ukazuje na slice košů (může být nil).
// Každý koš je pole `hmap.B` s velikostí B.
// Poloha v koši ukládá klíč a hodnotu pro jeden záznam mapy,
// plus byte tophash. Klíče a hodnoty jsou uloženy ve stejném
// záznamu koše, přičemž hodnoty následují klíče.
// Pokud jsou velikosti klíče/hodnoty velké, zapisují se nepřímo do
// overflow košů, začínajíc přes overflow ukazatele v hlavních koších.
count int // počet živých buněk; není rovno 0, pokud mapa má nějaké záznamy
flags uint8
B uint8 // log_2 počtu košů (může pojmout až 2^B záznamů)
noverflow uint16 // přibližný počet overflow košů
hash0 uint32 // hash seed
buckets unsafe.Pointer // pole košů 2^B, alokováno na haldě
oldbuckets unsafe.Pointer // předchozí pole košů 2^B, alokováno na haldě
nevacuate uintptr // čítač pokroku pro evakuaci (přesun košů do nových)
// pravda, když typ klíče nebo hodnoty má ukazatele, které je třeba skenovat
keysize uint8 // velikost typu klíče
valuesize uint8 // velikost typu hodnoty
elemsize uint16 // velikost klíč + hodnota (pro in-place uložení)
// ukazatel na slice overflow košů, alokováno na haldě
overflow *[]*bmap
}
// Příklad struktury `bmap` (zjednodušený)
// Typ koše.
type bmap struct {
// Rozložení koše je složité.
// Podrobnosti najdete v src/runtime/hashmap.go.
tophash [8]uint8 // 8 bajtů tophash (jeden na pár kv)
// následují klíče a pak hodnoty
// následuje overflow ukazatel
}