Суть в следующем: ваш язык уже снаряжен garbage collector (GC), НО время от времени появляются места, в которых есть конкретное место, в котором вы должны аллоцировать набор объектов и конкретное место, где вы хотите сразу весь этот набор почистить
Например, акторы: когда клиент подключается к приложению, мы достаем все нужные по нему данные, кладем их в память, обрабатываем, а когда клиент отключается, сохраняем и должны выгрузить из памяти
Для загразки и выгрузи из памяти GC должен будет сделать 100500 проверок того, не используется ли больше этот кусок и освободить его или оставить. Причем делать он будет это каждый свой цикл, пока не произойдет реальное освобождение.*
* - принцип GC зависит от языка, но среднестатистически так
А представьте, если бы мы могли воспользоваться какой-нибудь структурой, назовем ее Allocator с методами "create" и "destroy", которые позвляют явно указать "вот здесь создаем, а вот здесь чистим" и GC, вообще не будет лезть к тем данным, которые были созданы через Allocator
Разберем 3 пути реализации подобного на примере Go:
1. Заранее создать пустые буферы, сериализовать туда данные при создании и обнулять при удалении, а далее переиспользовать их по мере течения программы.
Вот вам пример реализации подобного поведегния на Slab алокаторе:
https://github.com/couchbase/go-slabПлюсы – это работает, из минусов – (1) контроль места сложнее, чем в 2-х других методах, (2) GC все-равно будет перепроверять эти объекты (хоть это и будет занимать меньше ресурсов), (3) (де)сериализация занимает ресурсы
2. Использовать С-шные байндинги и аллоцировать и освобождать память через них.
Одна из лучших статей + ссылка на либу по теме:
https://dgraph.io/blog/post/manual-memory-management-golang-jemalloc/И плюсов, это работает, из минусов, (1) сложная типизация, (2) может быть сложная (де)сериализация к и из структур Go
3. Эксперементальная фича ArenaAllocator
–
https://uptrace.dev/blog/golang-memory-arena.html–
https://medium.com/@esimov/go-memory-arenas-1ba930bf79c1–
https://www.youtube.com/watch?v=eglMl21DJz0Это практически идеальная реализация, которая очень похожа на то, как сделано в Zig и там это прекрасно работает
НО проблема в том, что это эксперементальная фича и авторы по-прежнему не уверены оставят ее или нет 😢
Главный поинт авторов: "Что если этим начнут пользоваться библиотеки, тем самым заставив использовать это польвателей" – с ним я согласен, но по-прежнему, данный вопрос можно решить флагом при компиляции: если флаг есть, использовать алокаторы, если нет, не использовать
Мне кажется подход с Аллокатором + GC очень оптимальным, потому что позволяет с одной стороны оставить язык простым для стандартных задач, но именно там, где нам нужно массивно работать с памятью иметь подходящие инструменты
Что скажете, даешь Аллокаторы в Go?