Представляем профайлер React

10 Сентября, 2018. Brian Vaughn (Брайан Вон)

React 16.5 добавляет поддержку нового плагина для профилирования: DevTools. Данный плагин использует экспериментальный Profiler API-интерфейс React для сбора информации о времени для каждого отображаемого компонента, для выявления узких мест производительности в приложениях React. Он будет полностью совместим с нашими функциями временной нарезки (time slicing) и приостановки (suspence).

Данная статья охватывает следующие темы:


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


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



Внимание!

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

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


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



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


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


Просмотр фиксаций


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

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

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



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

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


Фильтрация фиксаций


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


Пламенная диаграмма


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



Внимание!

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

Цвет полосы показывает, сколько времени заняла отрисовка компонента (и его потомки) в выбранной фиксации. Желтые компоненты занимают больше времени, голубые - меньше, а серые компоненты во время этой фиксации не отрисовывались вообще.


Например, фиксация, показанная выше, заняла в общей сложности 18,4 мс. Компонент Router был «самым дорогим» для отрисовки (потратив 18,4 мс). Большая часть этого времени пришлась на двух потомков: Nav (8,4 мс) и Route (7,9 мс). Остальное время было разделено между оставшимися потомками или было затрачено в собственном методе отрисовки компонента.

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



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



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


Диаграмма ранжирования


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



Внимание!

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

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


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


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


Приведенная выше диаграмма показывает, что компонент List отрисовывался 11 раз. Она также показывает, что каждый раз, когда он отображался, это был самый «дорогой» компонент в фиксации.

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



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



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


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


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

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



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



API трассировки по-прежнему является новым, и мы рассмотрим его более подробно в будущем посте.


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


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


Если ваше приложение имеет несколько «корней», после профилирования может появиться следующее сообщение:


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



Отсутствуют данные для отображения по выбранной фиксации


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


Видео для более глубокого погружения


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