Недавно я злоупотреблял WeakMap
для решения проблем производительности в Javascript.WeakMap
работает очень похоже на своего более сильного брата Map
. Вы предоставляете ключ и значение. Когда вам нужно получить значение для этого ключа, вы можете получить его из WeakMap
.
Разница между Map
и WeakMap
в том, что последняя не хранит ссылку на ключ, если сборщику мусора понадобится очистить его из памяти, WeakMap
скажет, что все в порядке, ключ и значение будут очищены одновременно.
Кэширование
Сила, которую дает нам эта характеристика, заключается в том, что мы можем начать кэшировать вещи без риска вызвать утечку памяти. Если ключ готов к сбору, кэш не будет проблемой на пути GC.
Мы можем реализовать функцию более высокого порядка под названием weakMemoize
, которая украсит нашу функцию слоем кэширования с помощью WeakMap
.
function weakMemoize(toDecorate) {
const cache = new WeakMap()
return function (value) {
if (!cache.has(value)) {
cache.set(value, toDecorate(value))
}
return cache.get(value)
}
}
Затем мы можем использовать для кэширования наши функции
const getKeys = weakMemoize((value) => {
return Object.keys(value)
})
const obj = { a: 10, b: 20, c: 30 }
getKeys(obj)
// second time the value is read from the cache.
getKeys(obj)
Я не беспокоюсь о потреблении памяти, поскольку всякий раз, когда obj
или getKeys
выходят из области видимости, сборщик мусора также будет собирать значения в карте. Я избегаю выполнения Object.keys
во второй раз без дополнительных сложностей в реализации моей функции.
Соображения
Следует принять во внимание несколько моментов. Ключом WeakMap
может быть только объект (object
или Array
), мы не можем использовать примитивное значение в качестве ключа.
Другое соображение заключается в том, что если у вас есть долгоживущие объекты, кэширование подобных вещей может быть не очень выгодным, много объектов будет оставаться в памяти, подумайте об использовании LRU кэша.
Также, вам не нужно реализовывать свой собственный weakMemoize
, есть хорошие реализации в npm.
Спасибо за прочтение!
Увидели проблему в моем посте? Пожалуйста, прокомментируйте или свяжитесь со мной в twitter.