Missed the action at this year's Chrome Dev Summit? Catch up with our playlist on YouTube. Watch now.

Упрощение и сокращение областей прорисовки

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

TL;DR

  • Изменение любого свойства, кроме transform и opacity, вызывает прорисовку.
  • Прорисовка зачастую является самой затратной частью конвейера. Избегайте ее при любой возможности.
  • Сокращайте области прорисовки путем размещения элементов на отдельных слоях и оптимизации анимации.
  • Оценивайте сложность прорисовки и затраты на нее с помощью средства профилирования Chrome DevTools. Снижайте сложность при любой возможности.

Если запускается перерасчет макета, всегда запускается и прорисовка, поскольку изменение геометрии элемента означает, что его пиксели нужно привести в порядок!

Полный конвейер пикселей

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

Конвейер пикселей без перерасчета макета.

Для быстрого определения проблем с прорисовкой используйте Chrome DevTools

С помощью Chrome DevTools можно быстро определить области, на которые распространяется прорисовка. Перейдите в DevTools и нажмите на клавиатуре клавишу Escape. На открывшейся панели перейдите на вкладку прорисовки и установите флажок "Show paint rectangles" (Показать прямоугольники прорисовки) :

Параметр отображения прямоугольников прорисовки в DevTools.

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

Страница, мигающая зеленым при прорисовке.

На шкале времени Chrome DevTools имеется средство, которое позволяет получить более подробные сведения, – профилировщик прорисовки. Чтобы включить его, перейдите на шкалу времени и установите флажок "Paint" вверху окна. Важно, чтобы этот флажок находился в установленном состоянии только при профилировании проблем с прорисовкой, поскольку, когда он установлен, потребляются дополнительные ресурсы и профилирование производительности даст искаженные результаты. Лучше всего использовать это средство, когда вам требуются сведения о том, какие объекты на странице были прорисованы.

Переключатель для включения профилирования прорисовки в Chrome DevTools.

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

Кнопка для открытия профилировщика прорисовки.

При щелчке профилировщика прорисовки открывается представление, в котором указано, какие объекты подверглись прорисовке, сколько это заняло времени, а также отдельные вызовы прорисовки, которые потребовались:

Профилировщик прорисовки Chrome DevTools.

Этот профилировщик позволяет определить и область, и сложность прорисовки (фактически это время, которое занимает прорисовка). А это именно те аспекты, которые необходимо исправлять, если избежать прорисовки совершенно невозможно.

Перемещайте на отдельные слои элементы, которые двигаются или исчезают с экрана

Прорисовка не всегда формирует одно изображение в памяти. На самом деле, при необходимости браузер может сформировать несколько изображений или слоев для компоновки.

Представление слоев для компоновки.

Преимущество этого подхода состоит в том, что элементы, которые регулярно заново прорисовываются или двигаются на экране с помощью свойств transform, можно обрабатывать, не затрагивая другие элементы. Это тоже самое, что и работа с графикой в Sketch, GIMP или Photoshop, где отдельные слои можно обрабатывать и располагать друг на друге для создания итогового изображения.

Лучший способ создания новыхе слоев – это использование свойства CSS will-change. Такой способ работает в Chrome, Opera и Firefox. Со значением transform это свойство создает новый слой:

.moving-element {
  will-change: transform;
}

Для браузеров, которые не поддерживают свойство will-change, но будут работать быстрее, если создавать слои, таких как Safari и Mobile Safari, необходимо воспользоваться (немного неправильно) трехмерным преобразованием для принудительного формирования нового слоя:

.moving-element {
  transform: translateZ(0);
}

Однако не следует создавать слишком много слоев, поскольку каждый из них занимает место в памяти и требует управления. Подробные сведения об этом приведены в разделе [Используйте свойства, вызывающие только компоновку, и контролируйте количество слоев] (stick-to-compositor-only-properties-and-manage-layer-count).

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

Сокращайте области прорисовки

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

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

Снижайте сложность прорисовки

При выполнении прорисовки одни операции требуют больше ресурсов, чем другие. Например, все, что связано с событием blur (тень и т. п.), будет прорисовываться дольше чем, скажем, красный квадрат. Однако для CSS это не всегда очевидно: строки background: red; и box-shadow: 0, 4px, 4px, rgba(0,0,0,0.5); не выглядят так, что по производительности они значительно отличаются, но на самом деле это так и есть.

Время на прорисовку части экрана.

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

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