Представляем React Profiler
React 16.5 добавляет поддержку нового плагина профилировщика DevTools. Этот плагин использует экспериментальный API профилировщика React для сбора информации о времени выполнения для каждого отображаемого компонента с целью выявления узких мест производительности в приложениях React. Он будет полностью совместим с нашими грядущими функциями time slicing и suspense.
В этом посте рассматриваются следующие темы:
Профилирование приложения
DevTools покажет вкладку «Profiler» для приложений, поддерживающих новый API профилирования:
Примечание:
react-dom
16.5+ поддерживает профилирование в DEV режиме. Для профилирования в production доступен пакетreact-dom/profiling
. Подробнее о том, как использовать этот пакет fb.me/react-profiling
Панель «Profiler» изначально будет пустой. Нажмите кнопку записи, чтобы начать профилирование:
После того как вы начали запись, DevTools будет автоматически собирать информацию о производительности при каждом рендеринге вашего приложения. Используйте свое приложение как обычно. Когда вы закончили профилирование, нажмите кнопку «Stop».
Предполагая, что ваше приложение рендерилось хотя бы один раз во время профилирования, DevTools покажет несколько способов просмотра данных о производительности. Мы рассмотрим каждый из них ниже.
Чтение данных о производительности
Просмотр коммитов
Концептуально React выполняет работу в два этапа:
- Этап рендеринга определяет какие изменения необходимо внести, например в DOM. На этом этапе React вызывает
render
, а затем сравнивает результат с предыдущим рендером. - Этап коммита (фиксации) — это когда React применяет любые изменения. (В случае React DOM — это когда React вставляет, обновляет и удаляет узлы DOM.) На этом этапе React также вызывает методы жизненного цикла такие, как
componentDidMount
иcomponentDidUpdate
.
Профилировщик DevTools группирует информацию о производительности по коммитам. Коммиты отображаются на гистограмме в верхней части профилировщика:
Каждый столбец на диаграмме представляет собой отдельный коммит, черным цветом помечен текущий выбранный коммит. Вы можете кликать по столбцам (или по кнопкам со стрелками влево/вправо), чтобы выбрать другой коммит.
Цвет и высота каждого столбца соответствуют тому, сколько времени потребовалось для рендеринга этого коммита. (Более высокие желтые столбцы занимали больше времени, чем короткие синие.)
Фильтрация коммитов
Чем дольше вы профилируете, тем больше раз будет рендериться ваше приложение. В некоторых случаях вы можете получить слишком много коммитов, чтобы их было легко обработать. Профилировщик предлагает механизм фильтрации, чтобы помочь в этом. Используйте его, чтобы указать порог, и профилировщик скроет все коммиты, которые были быстрее этого значения.
Flame chart диаграмма
Flame chart диаграмма представляет состояние вашего приложения для конкретного коммита.
Каждый столбец в диаграмме представляет React-компонент (например App
, Nav
).
Размер и цвет столбца показывают сколько времени потребовалось для рендера компонента и его дочерних компонентов.
(Ширина столбца показывает сколько времени было потрачено при последнем рендере. Цвет показывает сколько времени было потрачено как часть текущего коммита.)
Примечание:
Ширина столбца указывает сколько времени потребовалось для рендера компонента (и его дочерних компонентов) при последнем рендере. Если компонент не подвергался ререндеру как часть этого коммита, время представляет предыдущий рендер. Чем больше компонент, тем больше времени требуется на рендер.
Цвет столбца указывает сколько времени потребовалось компоненту (и его дочерним компонентам) для рендера в выбранном коммите. Желтые компоненты занимали больше времени, синие компоненты — меньше времени, а серые компоненты вообще не рендерелись во время текущего коммита.
Например, показанный выше коммит занял в общей сложности 18.4мс для рендера.
Компонент Router
оказался «самым дорогим» для рендера (занял 18.4мс).
Большая часть этого времени была связана с двумя его дочерними компонентами, Nav
(8.4мс) и Route
(7.9мс).
Остальное время было разделено между оставшимися дочерними компонентами или потрачено на собственный метод рендера компонента.
Вы можете кликать на компоненты, чтобы увеличивать или уменьшать масштаб диаграммы:
Клик по компоненту также выберет его и отобразит информацию на правой боковой панели, которая включает его props
и state
на момент этого коммита.
Вы можете углубиться в них, чтобы узнать больше о том, что компонент фактически рендерил во время коммита:
В некоторых случаях выбор компонента и переход между коммитами также может дать подсказку о том, почему компонент рендерился:
На изображении выше показано, что state.scrollOffset
изменился между коммитами.
Вероятно, это вызвало повторный рендер компонента List
.
Ранжированная диаграмма
Ранжированная диаграмма представляет собой отдельный коммит.
Каждая полоса на диаграмме представляет компонент React (например App
, Nav
).
Диаграмма упорядочена таким образом, что компоненты, рендер которых занимает больше всего времени, находятся наверху.
Примечание:
Время рендера компонента включает время, затраченное на рендер его дочерних компонентов поэтому компоненты, рендер которых занял больше всего времени, обычно находятся в верхней части дерева.
Как и в случае с flame chart диаграммой, вы можете увеличивать или уменьшать масштаб ранжированной диаграммы, нажимая на компоненты.
Диаграмма компонента
Иногда полезно узнать, сколько раз конкретный компонент рендерился во время профилирования. Диаграмма компонента предоставляет эту информацию в виде столбчатой диаграммы. Каждый столбец на диаграмме представляет время рендера компонента. Цвет и высота каждого столбца соответствуют тому, сколько времени потребовалось для рендера компонента по сравнению с другими компонентами в конкретном коммите.
На диаграмме выше показано, что компонент List
был отрендерен 11 раз.
Он также показывает, что каждый раз при рендере это был самый «дорогой» компонент в коммите (это означает, что он занимал больше всего времени).
Чтобы просмотреть эту диаграмму, дважды кликните на компонент, либо выберите компонент и кликните на значок синей гистограммы на правой панели сведений. Вы можете вернуться к предыдущей диаграмме, нажав кнопку «x» на правой панели деталей. Вы также можете дважды кликнуть по определенному столбцу, чтобы просмотреть дополнительную информацию об этой коммите.
Если выбранный компонент вообще не рендерился во время сеанса профилирования, будет показано следующее сообщение:
Взаимодействия
React недавно добавил еще один экспериментальный API для отслеживания причины обновления. «Взаимодействия» отслеживаемые этим API, также будут отображаться в профилировщике:
На изображении выше показан сеанс профилирования, в котором было отслежено четыре взаимодействия. Каждая строка представляет отслеживаемое взаимодействие. Цветные точки в строке обозначают коммиты, связанные с этим взаимодействием.
Вы также можете увидеть какие взаимодействия были отслежены для конкретного коммита на flame chart диаграмме и в отображении ранжированной диаграммы:
Вы можете перемещаться между взаимодействиями и коммитами, нажимая на них:
API трассировки все еще новый и мы расскажем о нем более подробно в одном из следующих постах.
Исправление проблем
Данные профилирования не записаны для выбранного root
Если ваше приложение имеет несколько «roots», после профилирования вы можете увидеть следующее сообщение:
Это сообщение означает, что не было записано никаких данных о производительности для root выбранного в панели «Элементы». В этом случае попробуйте выбрать другой root на этой панели, чтобы просмотреть информацию профилирования для этого root:
Нет данных о времени выполнения для выбранного коммита
Иногда коммит может быть настолько быстрым, что performance.now()
не дает DevTools какой-либо значимой информации о времени выполнения.
В этом случае будет показано следующее сообщение:
Подробное видео
В следующем видео показано, как профилировщик React можно использовать для обнаружения и улучшения узких мест в реальном приложении React.