Sobes.tech
Middle+

Golang-ში რუკა (მაპა) რამდენ ბაიტს იკავებს?

sobes.tech AI

პასუხი AI-სგან

Golang-да map-тың өлшемі тұрақты емес және көптеген факторларға байланысты:

  • Элементтердің саны: Элементтер саны көп болған сайын, оларды сақтау үшін көп жад қажет.
  • Кілттер мен мәндердің өлшемі: Әр кілт пен әр мән жадты алады. Жолдар, слайстар, құрылымдар — бұлар жалпы өлшемге әсер етеді.
  • hmap құрылымының қызметтік деректері: map — бұл hmap құрылымына сілтеме. Бұл құрылымда қызметтік өрістер бар:
    • элементтер саны
    • себеттерге (buckets) сілтемелер
    • көшірулер (өсу/азайту) саны
    • басқа метадеректер
  • Себеттердің өлшемі (buckets): Элементтер себеттерде сақталады. Әр себет тұрақты өлшемге ие (әдетте 8 кілт-мән жұбы), бірақ кілттер мен мәндердің деректері бөлек сақталады, себеттегі көрсеткіштер арқылы сілтемеленеді. Себеттерде пайдаланылмаған орын болуы мүмкін.
  • Толымдылық тығыздығы: Элементтер қосқанда map қайта хештелуі мүмкін және себеттер саны өседі, бұл жаңа жад бөлуін талап етеді.
  • Жадыны туралау: Go деректерді жадыда туралайды, бұл қосымша байттарды қажет етуі мүмкін дұрыс қол жеткізу үшін.

Осылайша, нақты байт санын атау мүмкін емес, себебі ол мазмұн мен map-тың өсуіне байланысты динамикалық түрде өзгереді. Төменгі шекара ( hmap және алғашқы себет үшін) және жоғарғы шекара (кілттер, мәндер, себеттер және қызметтік деректердің сомасы) бағалана алады, бірақ нақты өлшем Go-ның рантаймына тәуелді.

Өлшемді бағалау үшін unsafe пакетін немесе дебаг құралдарын қолдануға болады, бірақ олар нақты уақыттағы мазмұнға сәйкес өлшемді береді.

// `hmap` құрылымының мысалы (қарапайым)
// Бұл құрылым тікелей қолдануға арналмаған
// және оның өрістері Go нұсқаларына қарай өзгеруі мүмкін.
type hmap struct {
	// `hmap` форматы ../runtime/map.go файлында сипатталған.
	// Бұл хэш кестесі, себеттер Go heap-тан бөлінген.
	// hmap.buckets көрсеткіші себеттердің тізіміне сілтеме жасайды (nil болуы мүмкін).
	// Әр себет `hmap.B` элементтерінен тұрады, мұнда B себеттің өлшемі.
	// Себеттегі әрбір элемент бір map жазбасының кілті мен мәнін сақтайды,
	// plus tophash байты. Кілттер мен мәндер бір себет жазбасында сақталады,
	// мәндер кілттердің соңында орналасады.
	// Егер кілт/мән өлшемдері үлкен болса, олар жанама түрде overflow себеттеріне жазылады,
	// overflow көрсеткіштері арқылы негізгі себеттерден басталады.

	count     int // тірі ұяшықтар саны; map-те қандай да бір жазбалар болса, 0-ден басқа
	flags     uint8
	B         uint8  // себеттер санының логарифмі (2^B дейін орналастыра алады)
	noverflow uint16 // шамамен overflow себеттер саны
	hash0     uint32 // хэш тұқым

	buckets    unsafe.Pointer // 2^B себеттерінің массиві, heap-те бөлінген
	oldbuckets unsafe.Pointer // алдыңғы себеттердің массиві, heap-те бөлінген

	nevacuate uintptr // эвакуацияның прогрессі (көшіру себеттері)

	// кілт немесе мән типінде көрсеткіштер бар, олар сканерлеуді қажет етеді
	keysize  uint8 // кілт типінің өлшемі
	valuesize uint8 // мән типінің өлшемі
	elemsize  uint16 // кілт + мән өлшемі (орында сақтау үшін)

	// overflow себеттерінің тізіміне көрсеткіш, heap-те бөлінген
	overflow *[]*bmap
}

// `bmap` құрылымының мысалы (қарапайым)
// Себет типі.
type bmap struct {
	// Себеттің құрылымы күрделі.
	// Толығырақ үшін src/runtime/hashmap.go қараңыз.
	tophash [8]uint8 // 8 tophash байты (бірі әр kv жұбы үшін)
	// одан әрі кілттер мен мәндер
	// overflow көрсеткіші
}