THANK_GO Telegram 168
Скукоживание карт в Go

Вижу, не все могут поверить в коварство гошной карты, которая делает кусь не отдает память.

Характерный комментарий:

Если есть сервер на го с сессиями которые реализованы в виде мапы, то даже после отключения клиентов и удаления ключей из нее память не будет освобождаться?🤌

Штош. Давайте разбираться.

Вот наш клиент с идентификатором и телом в 40 байт:

type Client struct {
id uint64
body [40]byte
}


Создаем карту, добавляем 10К клиентов:

printAlloc("initial")

m := make(map[int]Client)
for i := range 10000 {
m[i] = Client{id: uint64(i)}
}

runtime.GC()
printAlloc("after create")


initial: heap size = 109 KB
after create: heap size = 1110 KB


Размер кучи вырос до 1100 KB. Удаляем все записи из карты:

for i := range 10000 {
delete(m, i)
}

runtime.GC()
printAlloc("after delete")


after delete: heap size = 1110 KB


Ни байтика не отдала, зараза!

Попробуем хранить указатели вместо значений:

m := make(map[int]*Client)
for i := range 10000 {
m[i] = &Client{id: uint64(i)}
}

for i := range 10000 {
delete(m, i)
}


after create: heap size = 898 KB
after delete: heap size = 429 KB


Почему часть памяти освободилась?

Здесь в памяти хранятся только указатели на клиентов, а сами значения (48B каждое) хранятся вне карты. Поэтому клиентов GC спокойно спокойно освобождает (ссылок-то на них больше нет), а вот внутренние структуры карты по-прежнему занимают память.

Напоследок предположим, что вместо легкого клиента у нас толстенький боди-позитивный с телом на 1024B:

type Client struct {
id uint64
body [1024]byte
}


m := make(map[int]Client)
for i := range 10000 {
m[i] = Client{id: uint64(i)}
}

for i := range 10000 {
delete(m, i)
}


after create: heap size = 11683 KB
after delete: heap size = 434 KB


Что за ерунда? Мы же используем значения, а не указатели, почему память освободилась?

Если значения в карте достаточно большие (больше 128B) Go автоматически хранит в карте не сами значения, а указатели на них. Поэтому после GC занятая клиентами память освободилась, и осталась только занятая самой картой память размером 400KB.

песочница (можете поменять версию на dev, и убедиться, что в Go 1.24 ничего не изменилось)

Такие дела.



tgoop.com/thank_go/168
Create:
Last Update:

Скукоживание карт в Go

Вижу, не все могут поверить в коварство гошной карты, которая делает кусь не отдает память.

Характерный комментарий:

Если есть сервер на го с сессиями которые реализованы в виде мапы, то даже после отключения клиентов и удаления ключей из нее память не будет освобождаться?🤌

Штош. Давайте разбираться.

Вот наш клиент с идентификатором и телом в 40 байт:

type Client struct {
id uint64
body [40]byte
}


Создаем карту, добавляем 10К клиентов:

printAlloc("initial")

m := make(map[int]Client)
for i := range 10000 {
m[i] = Client{id: uint64(i)}
}

runtime.GC()
printAlloc("after create")


initial: heap size = 109 KB
after create: heap size = 1110 KB


Размер кучи вырос до 1100 KB. Удаляем все записи из карты:

for i := range 10000 {
delete(m, i)
}

runtime.GC()
printAlloc("after delete")


after delete: heap size = 1110 KB


Ни байтика не отдала, зараза!

Попробуем хранить указатели вместо значений:

m := make(map[int]*Client)
for i := range 10000 {
m[i] = &Client{id: uint64(i)}
}

for i := range 10000 {
delete(m, i)
}


after create: heap size = 898 KB
after delete: heap size = 429 KB


Почему часть памяти освободилась?

Здесь в памяти хранятся только указатели на клиентов, а сами значения (48B каждое) хранятся вне карты. Поэтому клиентов GC спокойно спокойно освобождает (ссылок-то на них больше нет), а вот внутренние структуры карты по-прежнему занимают память.

Напоследок предположим, что вместо легкого клиента у нас толстенький боди-позитивный с телом на 1024B:

type Client struct {
id uint64
body [1024]byte
}


m := make(map[int]Client)
for i := range 10000 {
m[i] = Client{id: uint64(i)}
}

for i := range 10000 {
delete(m, i)
}


after create: heap size = 11683 KB
after delete: heap size = 434 KB


Что за ерунда? Мы же используем значения, а не указатели, почему память освободилась?

Если значения в карте достаточно большие (больше 128B) Go автоматически хранит в карте не сами значения, а указатели на них. Поэтому после GC занятая клиентами память освободилась, и осталась только занятая самой картой память размером 400KB.

песочница (можете поменять версию на dev, и убедиться, что в Go 1.24 ничего не изменилось)

Такие дела.

BY Thank Go!


Share with your friend now:
tgoop.com/thank_go/168

View MORE
Open in Telegram


Telegram News

Date: |

Telegram channels enable users to broadcast messages to multiple users simultaneously. Like on social media, users need to subscribe to your channel to get access to your content published by one or more administrators. The public channel had more than 109,000 subscribers, Judge Hui said. Ng had the power to remove or amend the messages in the channel, but he “allowed them to exist.” bank east asia october 20 kowloon 6How to manage your Telegram channel? Add the logo from your device. Adjust the visible area of your image. Congratulations! Now your Telegram channel has a face Click “Save”.!
from us


Telegram Thank Go!
FROM American