Автор оригинала: Marcell Toth.
Проверьте Оригинальная версия этой статьи на моем блоге разработчика.
Когда вы впервые узнаете о мемузаризации в JavaScript, это выглядит как Волшебный инструмент, который решает все ваши проблемы с производительностью Отказ Люди, как правило, начинают применять Memoize
За все, не думая о том, что это действительно делает. (Я знаю, что сделал)
Есть нагрузка на различные библиотеки памяти на NPM
Многие из них построены на действительно отличных идеях. Я не стремимся покрыть разные библиотеки здесь, это сделало бы действительно длинную статью. Одна важная вещь, чтобы понять, что На самом деле есть две действительно разные стратегии для воспоминания И, скорее всего, в какой-то момент у вас будет у вас есть упрецеляция как в вашем приложении. Так что большую часть времени, Вы должны использовать как минимум две разные помощники памяти (или одна библиотека с 2 различными конфигурациями).
Стратегия 1 – только последние входные вопросы
В этой стратегии только один результат (и один вход) запоминается помощником Отказ Если изменяемая функция вызывается с новым (набором) аргументов, старый результат выброшен, а новый результат сохраняется.
const complexCalculation(input) = memoize(...); complexCalculation(1); // NOT memoized complexCalculation(1); // memoized complexCalculation(2); // NOT memoized complexCalculation(1); // NOT memoized complexCalculation(2); // NOT memoized complexCalculation(2); // memoized
Это отлично подходит для сценариев, где есть единый источник правды, и где результаты, основанные на новых входах, недействительными в результате старых результатов. Например, для индексов над магазинами Redux преобразование данных сеанса/пользовательских данных и т. Д. После обновления redux я знаю, что селектор не будет запрашивать старого магазина, поэтому он безопасен (и эффективный) для отказа от старых результатов.
Преимущества:
- Постоянное и предсказуемое использование памяти. Используемая память всегда у нас больше всего размера последнего результата плюс размер последнего ввода.
- Скорость. Здесь нет Hashtree Lookup здесь, единственное влияние на производительность, проходя через помощник по мемузаризации, является стоимостью сравнения входов. Который – при использовании ссылочного равенства – практически нулю.
- Простота. Эти библиотеки действительно просты в реализации, так и использовании. Memoize-One Например, буквально находится в буквальном уровне 36 строк (не замидифицированного, простого к читаю) Tymertcript Code. При использовании этого вам не нужно беспокоиться о недействии кэша и его препятствиях, он будет Просто работа ™ Отказ
Недостатки:
- Не мемтизируется, когда несколько разных входов используются в переменном способе. Это может быть так, когда несколько разных модулей вашего кода (например, несколько компонентов React или несколько экземпляров одного и того же компонента реагирования) вызывают одну и ту же мему.
- Большинство из этих библиотек сравнивают входы, использующие эталонное равенство (для скорости), которые нуждаются в рассмотрении.
Примеры Немередность единой элементы По умолчанию: Memoize-One , повторно повторно , React.memo , Рейкт Угемер
крюк.
Стратегия 2 – На основании кэша на основе кэша
Это тот случай, когда необходимо запомнить несколько результатов. Принимая тот же пример, что и выше:
const complexCalculation(input) = memoize(...); complexCalculation(1); // NOT memoized complexCalculation(1); // memoized complexCalculation(2); // NOT memoized complexCalculation(1); // memoized complexCalculation(2); // memoized complexCalculation(2); // memoized
Теперь существует гораздо большее разнообразие реализации памяти на основе кеша, но в целом это гораздо более сложный случай, и, как мы все знаем:
С большой властью приходит большая ответственность.
Основное внимание при использовании памяти на основе кэша – Утечки памяти Отказ Обычно функция может быть вызвана с бесконечным количеством возможных аргументов. Если мы кэшируем результат каждого звонка в простой объект
или Карта
Мы будем – если мы не будем осторожны – выделите постоянно растущее количество памяти при этом. Вам либо необходимо убедиться, что будет сделано только приемлемо небольшое количество различных вызовов, или вам необходимо реализовать/использовать помощник памяти, который имеет какой-то политика выселения Отказ (См. Документацию для Memoiale – неизменяемая , которая имеет большое количество различных базовых магазинов для различных случаев использования.) Это довольно простая задача, но Неспособность сделать это может вызвать значительные головные боли Отказ Проблемы, связанные с утечкой памяти, которые всегда трудно отлаживать.
Есть также рассмотрение, хотите ли вы:
- Придерживаться референс-равенства. Это очень быстро выглядеть вверх, но может вызвать создание пропускания кэша и создания мусора при вызове с литералом встроенного объекта (например:
MemooizedFunction ({inverynput: 1})
всегда пропустите.) - Внедрить проверку в глубоком равенстве, в основном использование
Json.stringify
Отказ Это решает проблему выше, но создание струн JSON каждый раз медленнее примерно по порядку величины и не будет обращаться к функциям в качестве аргументов.
Преимущества:
- Запоминает несколько значений.
- Можно настроить для использования стоимости равенства.
- Труднее злоупотреблять и вызывать пропустить (при использовании стоимости равенства)
Недостатки:
- Медленнее, особенно при использовании ценности равенства.
- Легко случайно привести к утечки памяти.
- Поэтому необходимо тщательное планирование, которое будет сделано правильно.
Примеры Сомение на основе кеша :
- Fast-memoiese (По умолчанию используются
json.Stringify
С помощью простого объекта, который на самом деле медленный, так интересный выбор имени) - повторно повторно повторно (Сделано специально для повторного выбора, имеет несколько вариантов кэша)
- _.Мемиазображение (Использует
карта
и справочное равенство по умолчанию) - Memoize – неизменяемый (имеет несколько мощных вариантов кэша)
Используйте правильный инструмент для работы
Все стратегии и библиотеки, упомянутые выше (и многие другие), могут быть очень полезны для резки повышения производительности вашего приложения. Как с большинством других аспектов программирования (особенно в оптимизации) Вы должны сначала тщательно понять вашу проблему и посвятить некоторое время, чтобы выбрать правильное решение для вашей точной ситуации.
Если вам понравилось эту статью, не стесняйтесь проверить мой Разработчик Блог Где я делюсь больше историй, как это.
Если у вас есть какие-либо отзывы или желание узнать больше о теме со мной в сессии наставничества 1: 1, не стесняйтесь связаться со мной в любое время!