Слабые ссылки и финализаторы (WeakRef)
Недавно в блоге V8 появилась статья, посвящённая новому пропозалу WeakRef (Stage 3) — "Weak references and finalizers".
Попробую объяснить своими словами его суть на примере. Представьте, что у вас в браузере происходит какая-то обработка изображений, например, на них накладывается водяной знак (согласен, пример не очень реалистичный), а затем эти изображения как-то используются. Водяной знак накладывается функцией, которая интенсивно потребляет CPU. Изображения могут повторяться, поэтому, чтобы лишний раз не загружать процессор, мы создаём кеш изображений с водяным знаком в Map
, ключом пусть выступает название файла изображения. Но тут возникает проблема, если какое-то изображение не будет нами использоваться, оно всё равно будет находиться в памяти, так как Map
по ключу будет на него ссылаться (strong reference). Поэтому, чтобы наш Map
не отжирал лишнюю память, необходимо как-то определять такие ситуации и руками чистить кеш. Это не очень удобно.
Именно здесь на помощь приходит WeakRef. С помощью WeakRef можно создать слабую ссылку на изображение и записывать её по ключу вместо самого изображения:
const wr = new WeakRef(image);
cache.set(name, wr);
// для получения изображения
const ref = cache.get(name);
const image = ref.deref();
В этом случае сборщик мусора сможет самостоятельно определять ситуации, когда изображение в кеше уже не нужно и очищать память. Для очистки ключей из Map в пропозале предлагается использовать дополнительное API FinalizationGroup.
Интересный факт. В самом начале статьи даётся небольшой обзор уже входящих в стандарт WeakMap и WeakSet. Оказывается, что наиболее формальное название для отношения, которое используется в WeakMap — Ephemeron.