Использование строковой памяти в Голанге - PullRequest
0 голосов
/ 17 октября 2018

Я оптимизировал код, используя map [string] string , где значение карты было только "A" или "B".Поэтому я подумал, что, очевидно, карта [строка] bool была намного лучше, поскольку карта содержит около 50 миллионов элементов.

var a = "a"
var a2 = "Why This ultra long string take the same amount of space in memory as 'a'"
var b = true
var c map[string]string
var d map[string]bool

c["t"] = "A"
d["t"] = true

fmt.Printf("a: %T, %d\n", a, unsafe.Sizeof(a))
fmt.Printf("a2: %T, %d\n", a2, unsafe.Sizeof(a2))
fmt.Printf("b: %T, %d\n", b, unsafe.Sizeof(b))
fmt.Printf("c: %T, %d\n", c, unsafe.Sizeof(c))
fmt.Printf("d: %T, %d\n", d, unsafe.Sizeof(d))
fmt.Printf("c: %T, %d\n", c, unsafe.Sizeof(c["t"]))
fmt.Printf("d: %T, %d\n", d, unsafe.Sizeof(d["t"]))

И результат был:

a: string, 8
a2: string, 8
b: bool, 1
c: map[string]string, 4
d: map[string]bool, 4
c2: map[string]string, 8
d2: map[string]bool, 1

Во время тестирования я обнаружил что-то странное, почему a2 с очень длинной строкой используют 8 байтов, так же как a у которого только одна буква?

1 Ответ

0 голосов
/ 17 октября 2018

unsafe.Sizeof() не рекурсивно входит в структуры данных, он просто сообщает «мелкий» размер переданного значения.Цитирование из документа:

Размер не включает в себя память, на которую может ссылаться x. Например, если x - это слайс, Sizeof возвращает размер дескриптора слайса,не размер памяти, на которую ссылается срез.

Карты в Go реализованы как указатели, поэтому unsafe.Sizeof(somemap) сообщит размер этого указателя.

Строки в Goпросто заголовки, содержащие указатель и длину.См. reflect.StringHeader:

type StringHeader struct {
        Data uintptr
        Len  int
}

Так что unsafe.Sizeof(somestring) сообщит размер вышеуказанной структуры, который не зависит от длины значения string (которое является значениемполя Len).

Чтобы узнать фактические требования к памяти карты («глубоко»), см. Сколько памяти резервируют карты golang? , а также Какполучить объем памяти переменной в Golang?

Go сохраняет в памяти закодированные байтовые последовательности UTF-8 со значениями string.Встроенная функция len() сообщает длину байта string, поэтому в основном объем памяти, необходимый для хранения значения string в памяти:

var str string = "some string"

stringSize := len(str) + unsafe.Sizeof(str)

Такжене забывайте, что значение string может быть создано путем нарезки другой, более крупной строки, и, таким образом, даже если на исходную строку больше нет ссылок (и, следовательно, она больше не нужна), больший массив резервных копий все равно потребуется для хранения в памятидля меньшего фрагмента строки.

Например:

s := "some loooooooong string"
s2 := s[:2]

Здесь, даже если требование к памяти для s2 будет len(s2) + unsafe.Sizeof(str) = 2 + unsafe.Sizeof(str), тем не менее, весь резервный массив sбудут сохранены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...