Sobes.tech
Middle+

Koliko bajtova zauzima mapa (mapa) u Golang?

sobes.tech АИ

Одговор од АИ

Veličina mape u Golangu nije fiksna i zavisi od mnogo faktora:

  • Broj elemenata: Što više elemenata, to je potrebnije više memorije za njihovo skladištenje.
  • Veličina ključeva i vrednosti: Svaki ključ i vrednost zauzimaju memoriju. Stringovi, slice-ovi, strukture — sve to utiče na ukupnu veličinu.
  • Pomoćni podaci strukture hmap: mapa je pokazivač na strukturu hmap. Ova struktura sadrži pomoćna polja:
    • brojač elemenata
    • pokazivače na kante (buckets)
    • brojač migracija (povećanje/smanjenje)
    • i druge metapodatke
  • Veličina kanti (buckets): elementi se čuvaju u kantama. Svaka kanta ima fiksnu veličinu (obično 8 parova ključ-vrednost), ali podaci o ključevima i vrednostima se čuvaju odvojeno, na koje ukazuju pokazivači iz kante. Kante mogu sadržavati neiskorišćeni prostor.
  • Gustoća popunjenosti: Pri dodavanju elemenata, mapa može da se prehash-uje i poveća broj kanti, što zahteva alokaciju nove memorije.
  • Poravnanje memorije: Go poravnava podatke u memoriji, što može dovesti do dodatnih bajtova za obezbeđivanje pravilnog pristupa.

Dakle, nije moguće navesti tačan broj bajtova, jer se on dinamički menja u zavisnosti od sadržaja i rasta mape. Može se proceniti donja granica (memorija za hmap i prvu kantu) i gornja granica (zbir veličina ključeva, vrednosti, kanti i pomoćnih podataka), ali tačna veličina je određena runtime-om Go.

Za procenu veličine, može se koristiti paket unsafe ili alati za otklanjanje grešaka, ali oni daju veličinu u konkretnom trenutku za konkretan sadržaj.

// Primer strukture `hmap` ( pojednostavljeno)
// Struktura nije namenjena za direktnu upotrebu
// i njena polja mogu da se menjaju između verzija Go.
type hmap struct {
	// Napomena: format `hmap` je opisan u ../runtime/map.go.
	// To je hash tabela sa kantama alociranim iz go heap-a.
	// hmap.buckets pokazuje na slice od kanti (može biti nil).
	// Svaka kanta je niz od `hmap.B` unosa, gde je B veličina kante.
	// Pozicija u kanti čuva ključ i vrednost za jedan unos mape,
	// plus bajt tophash. Ključevi i vrednosti se čuvaju u istom
	// unosu kante, pri čemu vrednosti slede za ključeve.
	// Ako su veličine ključeva/vrednosti velike, one se indirektno upisuju u
	// overflow kante, počevši od overflow pokazivača u glavnim kantama.

	count     int // broj živih ćelija; nije 0 ako mapa ima unose
	flags     uint8
	B         uint8  // log_2 broja kanti (može da drži do 2^B unosa)
	noverflow uint16 // približan broj overflow kanti
	hash0     uint32 // seme za hash

	buckets    unsafe.Pointer // niz od 2^B kanti, alociran na heap-u
	oldbuckets unsafe.Pointer // prethodni niz od 2^B kanti, alociran na heap-u

	nevacuate uintptr // brojač napretka za evakuaciju (premestanje kanti u nove)

	// istina, kada tip ključa ili vrednosti sadrži pokazivače koje treba skenirati
	keysize  uint8 // veličina tipa ključa
	valuesize uint8 // veličina tipa vrednosti
	elemsize  uint16 // veličina ključa + vrednosti (za in-place skladištenje)

	// pokazivač na slice overflow kanti, alociran na heap-u
	overflow *[]*bmap
}

// Primer strukture `bmap` ( pojednostavljeno)
// Tip kante.
type bmap struct {
	// Raspored kante je složen.
	// Detalje pogledajte u src/runtime/hashmap.go.
	tophash [8]uint8 // 8 tophash bajtova (po kv par)
	// sleduju ključevi i zatim vrednosti
	// sleduje overflow pokazivač
}