Представляем the React Profiler

10 сентября, 2018 от Brian Vaughn

React 16.5 добавляет поддержку нового плагина профилировщика DevTools. Этот плагин использует экспериментальный API профилировщика React для сбора информации о времени выполнения для каждого отображаемого компонента с целью выявления узких мест производительности в приложениях React. Он будет полностью совместим с нашими грядущими функциями time slicing и suspense.

В этом посте рассматриваются следующие темы:

Профилирование приложения

DevTools покажет вкладку «Profiler» для приложений, поддерживающих новый API профилирования:

New DevTools

Примечание:

react-dom 16.5+ поддерживает профилирование в DEV режиме. Для профилирования в production доступен пакет react-dom/profiling. Подробнее о том, как использовать этот пакет fb.me/react-profiling

Панель «Profiler» изначально будет пустой. Нажмите кнопку записи, чтобы начать профилирование:

Click

После того, как вы начали запись, DevTools будет автоматически собирать информацию о производительности при каждом рендеринге вашего приложения. Используйте свое приложение, как обычно. Когда вы закончили профилирование, нажмите кнопку «Stop».

Click

Предполагая, что ваше приложение рендерилось хотя бы один раз во время профилирования, DevTools покажет несколько способов просмотра данных о производительности. Мы рассмотрим каждый из них ниже.

Чтение данных о производительности

Просмотр коммитов

Концептуально React выполняет работу в два этапа:

  • Этап рендеринга определяет, какие изменения необходимо внести, например в DOM. На этом этапе React вызывает render а затем сравнивает результат с предыдущим рендером.
  • Этап коммита (фиксации) это когда React применяет любые изменения. (В случае React DOM это когда React вставляет, обновляет и удаляет узлы DOM.) На этом этапе React также вызывает методы жизненного цикла, такие как componentDidMount и componentDidUpdate.

Профилировщик DevTools группирует информацию о производительности по коммитам. Коммиты отображаются на гистограмме в верхней части профилировщика:

Bar chart of profiled commits

Каждый столбец на диаграмме представляет собой отдельный коммит, черным цветом помечен текущий выбранный коммит. Вы можете кликать по столбцам (или по кнопкам со стрелками влево/вправо) чтобы выбрать другой коммит.

Цвет и высота каждого столбца соответствуют тому, сколько времени потребовалось для рендеринга этого коммита. (Более высокие желтые столбцы занимали больше времени, чем короткие синие.)

Фильтрация коммитов

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

Filtering commits by time

Flame chart диаграмма

Flame chart диаграмма представляет состояние вашего приложения для конкретного коммита. Каждый столбец в диаграмме представляеи React компонент (например App, Nav). Размер и цвет столбца показывают, сколько времени потребовалось для рендера компонента и его дочерних компонентов. (Ширина столбца показывает, сколько времени было потрачено при последнем рендере. Цвет показывает, сколько времени было потрачено как часть текущего коммита.)

Example flame chart

Примечание:

Ширина столбца указывает, сколько времени потребовалось для рендера компонента (и его дочерних компонентов) при последнем рендере. Если компонент не подвергался ререндеру как часть этого коммита, время представляет предыдущий рендер. Чем больше компонент, тем больше времени требуется на рендер.

Цвет столбца указывает, сколько времени потребовалось компоненту (и его дочерним компонентам) для рендера в выбранном коммите. Желтые компоненты занимали больше времени, синие компоненты — меньше времени, а серые компоненты вообще не рендерелись во время текущего коммита.

Например, показанный выше коммит занял в общей сложности 18.4мс для рендера. Компонент Router оказался «самым дорогим» для рендера (taking 18.4мс). Большая часть этого времени была связана с двумя его дочерними компонентами, Nav (8.4мс) и Route (7.9мс). Остальное время было разделено между оставшимися дочерними компонентами или потрачено на собственный метод рендера компонента.

Вы можете увеличивать или уменьшать масштаб диаграммы, кликая на компоненты: Click on a component to zoom in or out

Клик по компоненту также выберет его и отобразит информацию на правой боковой панели, которая включает его props и state на момент этого коммита. Вы можете углубиться в них, чтобы узнать больше о том, что компонент фактически рендерил во время коммита:

Viewing a component's props and state for a commit

В некоторых случаях выбор компонента и переход между коммитами также может дать подсказку о том, почему компонент рендерился:

Seeing which values changed between commits

На изображении выше показано, что state.scrollOffset изменился между коммитами. Вероятно, это вызвало повторный рендер компонента List.

Ранжированная диаграмма

Ранжированная диаграмма представляет собой отдельный коммит. Каждая полоса на диаграмме представляет компонент React (например App, Nav). Диаграмма упорядочена таким образом, что компоненты, рендер которых занимает больше всего времени, находятся наверху.

Example ranked chart

Примечание:

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

Как и в случае с flame chart диаграммой, вы можете увеличивать или уменьшать масштаб ранжированной диаграммы, нажимая на компоненты.

Диаграмма компонента

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

Example component chart

На диаграмме выше показано, что компонент List был отрендерен 11 раз. Он также показывает, что каждый раз при рендере это был самый «дорогой» компонент в коммите (это означает, что он занимал больше всего времени).

Чтобы просмотреть эту диаграмму дважды кликните на компонент, либо выберите компонент и кликните на значок синей гистограммы на правой панели сведений. Вы можете вернуться к предыдущей диаграмме, нажав кнопку «x» на правой панели деталей. Вы также можете дважды кликнуть по определенному столбцу, чтобы просмотреть дополнительную информацию об этой коммите.

How to view all renders for a specific component

Если выбранный компонент вообще не рендерился во время сеанса профилирования, будет показано следующее сообщение:

No render times for the selected component

Взаимодействия

React недавно добавил еще один экспериментальный API для отслеживания причины обновления. «Взаимодействия» отслеживаемые этим API, также будут отображаться в профилировщике:

The interactions panel

На изображении выше показан сеанс профилирования, в котором было отслежено четыре взаимодействия. Каждая строка представляет отслеживаемое взаимодействие. Цветные точки в строке обозначают коммиты, связанные с этим взаимодействием.

Вы также можете увидеть, какие взаимодействия были отслежены для конкретного коммита, на flame chart диаграмме и в отображении ранжированной диаграммы:

List of interactions for a commit

Вы можете перемещаться между взаимодействиями и коммитами, нажимая на них:

Navigate between interactions and commits

API трассировки все еще новый, и мы расскажем о нем более подробно в одном из следующих постах.

Исправление проблем

Данные профилирования не записаны для выбранного root

Если ваше приложение имеет несколько «roots», после профилирования вы можете увидеть следующее сообщение: No profiling data has been recorded for the selected root

Это сообщение означает, что не было записано никаких данных о производительности для root выбранного в панели «Элементы». В этом случае попробуйте выбрать другой root на этой панели, чтобы просмотреть информацию профилирования для этого root:

Select a root in the "Elements" panel to view its performance data

Нет данных о времени выполнения для выбранного коммита

Иногда коммит может быть настолько быстрым, что performance.now() не дает DevTools какой-либо значимой информации о времени выполнения. В этом случае будет показано следующее сообщение:

No timing data to display for the selected commit

Подробное видео

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