Spec-Zone.ru › Redux 3

Redux FAQ: Производительность

Содержание

  • Насколько хорошо Redux масштабируется с точки зрения производительности и архитектуры?
  • Не будет ли медленным вызов «всех моих редьюсеров» для каждого действия?
  • Нужно ли мне глубоко клонировать своё состояние в редьюсере? Разве копирование состояния не будет медленным?
  • Как можно уменьшить количество обновлений хранилища?
  • Приведёт ли наличие «одного дерева состояний» к проблемам с памятью? Займёт ли отправка многих действий много памяти?

Производительность

Насколько хорошо Redux масштабируется с точки зрения производительности и архитектуры?

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

Работа Redux обычно делится на несколько областей: обработка действий в мидлваре и редьюсерах (включая дублирование объектов для неизменяемых обновлений), уведомление подписчиков после отправки действий и обновление компонентов пользовательского интерфейса на основе изменений состояния. Хотя для каждой из этих областей в достаточно сложных ситуациях вполне возможно возникновение проблем с производительностью, в реализации Redux нет ничего изначально медленного или неэффективного. На самом деле, React Redux, в частности, сильно оптимизирован для сокращения ненужных перерисовок, а React-Redux v5 демонстрирует заметные улучшения по сравнению с предыдущими версиями.

Redux может не быть таким эффективным «из коробки» по сравнению с другими библиотеками. Для максимальной производительности отрисовки в приложении React состояние должно быть храниться в нормализованной форме, многие отдельные компоненты должны быть подключены к хранилищу вместо нескольких, а подключённые компоненты списков должны передавать идентификаторы элементов своим подключённым дочерним элементам списка (что позволяет элементам списка искать свои данные по идентификатору). Это сводит к минимуму общее количество отрисовок. Использование кеширующих функций-селекторов также является важным фактором производительности.

Что касается архитектуры, существует мнение, что Redux хорошо работает для проектов и команд разного размера. Redux в настоящее время используется сотнями компаний и тысячами разработчиков, с несколькими сотнями тысяч ежемесячных установок из NPM. Один разработчик сообщил:

для масштаба у нас есть ~500 типов действий, ~400 случаев редьюсеров, ~150 компонентов, 5 мидлваров, ~200 действий, ~2300 тестов

Дополнительная информация

Документация

  • Руководства: Структурирование редьюсеров - Нормализация формы состояния

Статьи

  • Как масштабировать приложения React (сопровождающая лекция: Масштабирование приложений React)
  • Высокопроизводительный Redux
  • Улучшение производительности React и Redux с помощью Reselect
  • Инкапсуляция дерева состояния Redux
  • React/Redux Ссылки: Производительность - Redux

Обсуждения

  • #310: Кто использует Redux?
  • #1751: Проблемы производительности с большими коллекциями
  • React Redux #269: Connect может использоваться с пользовательским методом subscribe
  • React Redux #407: Переписать connect для лучшей производительности и расширяемости
  • React Redux #416: Переписать connect для лучшей производительности и расширяемости
  • Redux против MobX TodoMVC Benchmark: #1
  • Reddit: Какое лучшее место для хранения начального состояния?
  • Reddit: Помощь в проектировании состояния Redux для одностраничного приложения
  • Reddit: Проблемы производительности Redux с большим объектом состояния?
  • Reddit: React/Redux для приложений сверхбольшого масштаба
  • Twitter: Масштабирование Redux
  • Twitter: График сравнения Redux и MobX - форма состояния Redux имеет значение
  • Stack Overflow: Как оптимизировать небольшие обновления свойств вложенных компонентов?
  • Лог чата: производительность React/Redux - обновление списка Todo с 10 000 элементов
  • Лог чата: производительность React/Redux - одно подключение против множества подключений

Не будет ли медленным вызов «всех моих редьюсеров» для каждого действия?

Важно отметить, что хранилище Redux фактически содержит только одну функцию редьюсера. Хранилище передает текущее состояние и отправленное действие этой единственной функции редьюсера, позволяя редьюсеру обработать ситуацию соответствующим образом.

Очевидно, что попытка обработать каждое возможное действие в одной функции не масштабируется хорошо, просто с точки зрения размера функции и читаемости, поэтому имеет смысл разделить фактическую работу на отдельные функции, которые могут вызываться верхнеуровневым редьюсером. В частности, рекомендуемой моделью является наличие отдельной функции суб-редьюсера, ответственной за управление обновлениями конкретного среза состояния по определенному ключу. combineReducers() который поставляется с Redux, является одним из многих возможных способов достижения этого. Также настоятельно рекомендуется хранить состояние вашего хранилища как можно более плоским и нормализованным. В конечном итоге, вы сами определяете организацию вашей логики редьюсеров.

Однако, даже если у вас есть много различных функций редьюсеров, составленных вместе, и даже при глубоко вложенном состоянии, скорость редьюсера вряд ли станет проблемой. Двигатели JavaScript способны выполнять очень большое количество вызовов функций в секунду, и большинство ваших редьюсеров, вероятно, просто используют оператор switch и по умолчанию возвращают существующее состояние в ответ на большинство действий.

Если вы всё же обеспокоены производительностью редьюсеров, вы можете использовать утилиту, такую как redux-ignore или reduxr-scoped-reducer, чтобы убедиться, что только определённые редьюсеры реагируют на определённые действия. Вы также можете использовать redux-log-slow-reducers, чтобы выполнить некоторые бенчмаркинг-тесты производительности.

Дополнительная информация

Обсуждения

  • #912: Предложение: утилита фильтрации действий
  • #1303: Производительность Redux с большим хранилищем и частыми обновлениями
  • Stack Overflow: Состояние в приложении Redux имеет свойство с именем редьюсера
  • Stack Overflow: Как Redux обрабатывает глубоко вложенные модели?

Нужно ли мне глубоко клонировать своё состояние в редьюсере? Разве копирование состояния не будет медленным?

Неизменяемое обновление состояния обычно подразумевает создание не глубоких копий, а поверхностных. Поверхностные копии намного быстрее, чем глубокие, потому что копируются меньше объектов и полей, и это фактически сводится к перемещению указателей.

Однако, для каждого уровня вложенности, который изменяется, вам необходимо создать скопированный и обновлённый объект. Хотя это не должно быть особенно дорого, это ещё одна причина, почему ваше состояние должно быть нормализованным и поверхностным, если это возможно.

Распространённое заблуждение Redux: необходимо глубокое клонирование состояния. Реальность: если что-то внутри не изменилось, сохраните его ссылку!

Дополнительная информация

Документация

  • Руководства: Структурирование редьюсеров - Предварительные понятия
  • Руководства: Структурирование редьюсеров - Шаблоны неизменяемых обновлений

Обсуждения

  • #454: Обработка больших состояний в редьюсере
  • #758: Почему состояние нельзя изменять?
  • #994: Как сократить объём кода при обновлении вложенных сущностей?
  • Twitter: распространённое заблуждение - глубокое клонирование
  • Клонирование объектов в JavaScript

Как можно уменьшить количество обновлений хранилища?

Redux уведомляет подписчиков после каждого успешно отправленного действия (т. е. действие достигло хранилища и было обработано редьюсерами). В некоторых случаях может быть полезно сократить количество вызовов подписчиков, особенно если создатель действия отправляет несколько отдельных действий подряд.

Если вы используете React, обратите внимание, что вы можете улучшить производительность нескольких синхронных диспетчеризаций, обернув их в ReactDOM.unstable_batchedUpdates(), но этот API экспериментальный и может быть удалён в любой версии React, поэтому не полагайтесь на него слишком сильно. Посмотрите на redux-batched-actions (высокоуровневый редьюсер, который позволяет отправлять несколько действий, как одно, и «распаковывать» их в редьюсере), redux-batched-subscribe (улучшитель хранилища, который позволяет сглаживать вызовы подписчиков для нескольких диспетчеризаций) или redux-batch (улучшитель хранилища, который обрабатывает отправку массива действий с одним уведомлением для подписчиков).

Дополнительная информация

Обсуждения

  • #125: Стратегия избегания каскадных рендеров
  • #542: Идея: пакетирование действий
  • #911: Пакетные действия
  • #1813: Использование цикла для поддержки отправки массивов
  • React Redux #263: Огромная проблема производительности при отправке сотен действий

Библиотеки

  • Каталог дополнений Redux: Хранилище - Подписки на изменения

Будет ли наличие «одного дерева состояния» вызывать проблемы с памятью? Будет ли отправка многих действий занимать много памяти?

Во-первых, с точки зрения использования памяти, Redux ничем не отличается от любой другой JavaScript библиотеки. Единственное отличие заключается в том, что все различные ссылки на объекты вложены вместе в одно дерево, вместо того, чтобы быть, возможно, сохранёнными в различных независимых экземплярах моделей, как, например, в Backbone. Во-вторых, типичное приложение Redux, вероятно, будет иметь несколько меньше использования памяти, чем эквивалентное приложение Backbone, потому что Redux поощряет использование простых JavaScript объектов и массивов, а не создание экземпляров моделей и коллекций. Наконец, Redux хранит только одну ссылку на дерево состояния за раз. Объекты, на которые больше нет ссылок в этом дереве, будут удалены сборщиком мусора, как обычно.

Redux сам по себе не хранит историю действий. Однако Redux DevTools хранят действия, чтобы их можно было воспроизвести, но они обычно включены только во время разработки, а не используются в производстве.

Дополнительная информация

Документация

  • Документация: Асинхронные действия

Обсуждения

  • Stack Overflow: Есть ли способ «зафиксировать» состояние в Redux, чтобы освободить память?
  • Stack Overflow: Может ли хранилище Redux привести к утечке памяти?
  • Stack Overflow: Redux и ВСЕ состояние приложения
  • Stack Overflow: Заботы об использовании памяти при управляемых компонентах
  • Reddit: Где лучше всего хранить начальное состояние?

© 2015–2017 Dan Abramov
Licensed under the MIT License.
http://redux.js.org/docs/faq/Performance.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API