Про интересное: intern package proposal
Практически все разработчики сталкиваются с проблемой уникальности данных на уровне приложения. Чаще всего это вопрос удаления повтора строк, т.к. именно этот тип данных является самым «ходовым» в случае работы с хранилищами. А где хранилища, там и кеши и вопрос о затратах памяти. И рано или поздно, в любой достаточно сложной системе кеширования встает вопрос дедупликации - хранить повторяющиеся строки уж очень дорого на больших обьемах данных.
Неофиты спросят: «а в чем проблема? Почему нельзя использовать обычный словарь под мьютексом?». И ведь правда, мы можем использовать тип map
для хранения уникальных значений любых сравниваемых типов. По скорости, словарь из стандартной библиотеки, превзойдут только уж совсем специализированные словари, которые большинство писать никогда не будет. Однако у этого подхода есть один существенный, но критический вопрос: как удалять ключи которых больше нет в нашей системе?
В языках со сборщиком мусора, типо Java и C#, для решения этой проблемы есть специализированные типы (WeakHashMap
, WeakSet
) которые автоматически удаляют ключи, на которые никто больше не ссылается. Под капотом практически все они используют weak reference (слабая ссылка, если только она ссылается на переменную, то сборщик мусора имеет право собрать переменную). Однако разработчики компилятора Go активно сопротивляются внедрению слабых ссылок в язык. Причины тому разные, но основная мысль кроется в нежелании усложнять рантайм и сборщик мусора без «лишней» необходимости.
Однако если чему-то сопротивляться, это не значит, что в этом чем-то пропадет потребность. Модуль go4.org/intern содержит в себе реализацию такой системы дедупликации значений. Авторами этого пакета являются разработчики Tailscale, часть из которых либо являлись частью Go Core Team в прошлом, либо активно работали над Go компилятором извне. Сам модуль используется внутри inet.af/netaddr который, в свою очередь, тянут в том числе и большие проекты.
Недостаток у go4.org/intern один: написан он с очень большим процентом черной магии, часть из которой еще и сильно ненадежна. Настолько ненадежна, что создателям модуля пришлось сделать (и регулярно обновлять) дополнительный модуль go4.org/unsafe/assume-no-moving-gc единственная цель которого, это убедиться, что сборщик мусора в Go все еще не двигает объекты в памяти хипа.
Проблема стала настолько явной, что Михаэль Кнызэк (один из ключевых разработчиков рантайма Go) предложил решить проблему уже на уровне стандартной библиотеки. Дескать не дело это, что модуль от которого зависит примерно 0,1% всей экосистемы (что достаточно много), может работать только в текущей внутрянке Go. Да и на дженерики бы уже неплохо все перенести. Предложенное API достаточно простое: есть одна глобальная функция которая возвращает враппер вокруг переменной и гарантирует ее уникальность в памяти. Враппер же нужен для быстрого сравнения уникальных значений между собой. А вся магия будет скрыта внутри райнтайма, который самостоятельно будет удалять переменные на которых больше никто не ссылается.
На мой взгляд, это попытка в очередной раз отложить внедрение слабых ссылок, потребность в которых назрела и перезрела уже давно. Однако меня устроит и такой вариант развития событий, ибо уже лучше чем ничего или магия которая может в любой момент развалиться.
>>Click here to continue<<