Пакет unique

Пакет unique (Go 1.23+) помогает сэкономить память, если обрабатываются неуникальные значения.

Рассмотрим пример. У нас есть генератор слов:

const nDistinct = 100
const wordLen = 40
generate := wordGen(nDistinct, wordLen)

fmt.Println(generate())
// nlfgseuif...
fmt.Println(generate())
// anixapidn...
fmt.Println(generate())
// czedtcbxa...

Размер словаря ограничен (100 слов), так что генерируемые значения будут часто повторяться.

Сгенерим 10000 слов и запишем их в срез строк:

words = make([]string, nWords)
for i := range nWords {
    words[i] = generate()
}
Memory used: 622 KB

10К слов заняли 600 Кб в куче.

Попробуем другой подход. Используем unique.Handle, чтобы назначить дескриптор каждому уникальному слову, и будем хранить эти дескрипторы вместо самих слов:

words = make([]unique.Handle[string], nWords)
for i := range nWords {
    words[i] = unique.Make(generate())
}
Memory used: 95 KB

100 Кб вместо 600 Кб — в 6 раз меньше памяти.

Функция Make создает уникальный дескриптор для значения любого comparable-типа. Она возвращает ссылку на «каноническую» копию значения в виде объекта Handle.

Два Handle равны только в том случае, если равны исходные значения. Сравнение двух Handle эффективно, потому что сводится к сравнению указателей.

Под капотом пакет unique ведет глобальный конкурентно-безопасный кеш всех добавленных значений, гарантируя их уникальность и повторное использование.

песочница

★ Подписывайтесь на новые заметки.