Pull to refresh

Comments 17

const functions = new Map<Function, Hash>()
const compositionsByHash = new Map<string, Composition<any, any>>()

Ай-ай-ай, утечка памяти же будет...


Кстати, зачем вам вообще свойства tail и head, если все что нужно уже лежит в list?

Этот вопрос задаю в конце статьи.
Устроит ли всех WeakMap или важнее указывать лимит кеша, или нужен лимит кэша на основе последних вызванных функций?
Проблема выглядит иначе, если использовать только чистые функции не ссылающиеся на свои замыкания (что потенциально опасно в любой композиции и мемоизации), а оставить только унарные или каррированные с переиспользованием уже созданных.

Tail и head — это часть другой реализации, где каждой композиции заводится пространство мемоизации. Таким образом композиции могут переиспользвать кэши друг друга. На гитхаб упрощённый вариант, который работает только со списком.

Любой обработчик события должен быть так или иначе привязан к компоненту, а для этого он обязан быть различным в каждом компоненте.


Любое применение вашего compose к обработчику событий в пересоздаваемом компоненте даст утечку памяти.

Почему обязан? Обработчик что-то берёт из замыкания? Он обращается к this? Значит он тесно связан с внутренней логикой компонента. Это не функциональный подход.
Такой обработчик нельзя использовать в композиции, особенно если он обращается не к лексическому this.
Строго говоря на все события одного типа может быть один обработчик. Это хороший повод подумать о дата флоу внутри приложения.

Я привёл пример с обработчиками событий на примере реакта.

Да, согласен, сглупил: this и правда необязателен.


Но у вашего кода все равно утечка памяти. id-то, как правило, может быть произвольным, а значит и compose(dispatch, makeAction, contsant(id)) будут накапливаться.

Это вопрос к тому, кому какие кэши нужны и в каких случаях.
Используйте WeakMap.

Вообще, что бы не было подобных очевидных вопросов, надо предложить несколько базовых стратегий и возможность подставить другое middleware для кэша. Пусть этот вопрос будет за скоупом npm пакета.

Тут стоит ещё учесть, что weakMap не будет работать с не-объектами. И пример из комментария майора придётся переписать, закешировав где-нибудь constant(id).

Композиция, или в данном случае скорее pipe (так как слева направо), еще хорошо реализуется простым Array.reduce:

[func1, func2, func3].reduce( (val, func) => func(val), initialParam );
Очень странный комментарий.
А как же эквивалентность, переиспользуемость и мемоизация всего это добра?

shammasov вопрос: у вас богатый опыт работы с weakMap? я в одном проекте ради удобства организовал глубокую мемоизацию за счёт вложенных weakMap-ов. Удобно, но это немного мешает спать, т.к. нет к ним у меня пока доверия. И дебажить утечки памяти сильно мешают (постоянно все пути ведут в Рим в очередной weakMap). Вы могли бы их рекомендовать в боевому применению на больших объёмах?

На самом деле, вместо WeakMap можно использовать символ, если вы достаточно доверяете самому себе.

Не очень понял вас. Можно на примере?


const map = new WeakMap();
map.set({}, 1); // map { %obj: 1 }
gc();
map; // map {}

Как это повторить используя символы?

Если вам нужно просматривать содержимое WeakMap в целях диагностики — то символы тут, конечно же, не помогут.

Но зачем так делать, если можно сделать Heap Snapshot и для любого объекта увидеть всех его настоящих ретайнеров, а не вспомогательные WeakMap?

Честно говоря я окончательно потерял нить беседы. Примером выше я хотел показать не просмотр содержимого, а суть слабых ссылок. Что ты пользуешься ими и не думаешь об утечках. Не пишешь всякие фабрики селекторов и прочую муть. Просто и элегантно. Я не очень понял вас, как можно сделать самодельные WeakMap-ы без слабых ссылок, но с использованием символов. Или вы не об этом говорили?


Касательно retainer-ов — я тут совсем поплыл. Вам случаем не попадалось какого-нибудь крутого мануала по профилированию утечек? Прошлый раз когда я пытался понять куда уплывает память, я в 95%+ случаях попадал в эти чёртовы weakMap-ы на каком-нибудь 15 уровне вложенности, и ничего не мог понять. Зачем они там вообще отображаются? о_О

Я не очень понял вас, как можно сделать самодельные WeakMap-ы без слабых ссылок, но с использованием символов. Или вы не об этом говорили?

Именно об этом я и говорил.


const symbol = Symbol("...");
// map.set({}, 1);
({})[symbol] = 1;
gc();

Зачем они там вообще отображаются?

Затем, что недоработка инструментария. В .NET, кстати, такая же ерунда с ConditionalWeakTable.

А ну да, точно. Под вечер мозг совсем плохо работает. Sorry :) Про подобный подход знал.

Давайте оставим кэширование каждому на своё устмотрение. Идеального алгоритма не существует. Не надо устраивать бои по вопросам кэша.
Sign up to leave a comment.

Articles