Подробно о композиции слоя (композита)

внешний интерфейс
Подробно о композиции слоя (композита)

Недавно я написал статью о том, как использовать Chrome DevTools.Оптимизация анимации карты Gaodeв статье, в которой упоминается композит, но не вдается в подробности. После долгих раздумий я все же чувствую, что необходимо еще раз подвести итоги.

1. Что такое композит?

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

Как только страница загружается и анализируется, она представляется в браузере в виде структуры, знакомой многим веб-разработчикам: DOM. Однако при рендеринге страницы браузер имеет ряд промежуточных представлений, которые напрямую не доступны разработчику. Наиболее важными из этих структур являются слои.

На данный момент существует концепция слоев. Перевод композита — это то, что мы часто называем синтезом, так как же это работает?

2. RenderLayers и GraphicsLayers

Сначала опубликуйте блок-схему, а мы уточним позже:
layer trees
На самом деле в Chrome есть несколько разных типов слоев:

  • Слой рендеринга RenderLayers, который отвечает за соответствующее поддерево DOM.
  • GraphicsLayers Графический слой, отвечающий за соответствующее поддерево RenderLayers.

Упоминание RenderLayers должно сказать RenderObjects :
Объекты RenderObject поддерживают древовидную структуру, объекты RenderObject знают, как отрисовывать содержимое узла, и отрисовывают узлы, посылая необходимые вызовы отрисовки в GraphicsContext.

Каждый GraphicsLayer имеет GraphicsContext, а GraphicsContext отвечает за вывод растрового изображения слоя. Растровое изображение хранится в общей памяти и загружается в графический процессор в виде текстуры. Наконец, графический процессор синтезирует несколько растровых изображений и затем рисует их на экране. , в этот момент наша страница также отображается на экране.

Контекст рисования GraphicsContext отвечает за отрисовку пикселей на экране (этот процесс заключается в том, чтобы сначала записать данные на уровне пикселей в растровое изображение, а затем отобразить их на дисплее). собственная библиотека 2D-графики)


Некоторые специальные слои рендеринга считаются композитными слоями, которые имеют отдельный GraphicsLayer, в то время как другие слои рендеринга, которые не являются композитными слоями, имеют общий слой с первым родительским слоем, имеющим GraphicsLayer.

3. Составной неявный синтез

Для неявного синтезаCSS GPU AnimationОн описывается таким образом:

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


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

Давайте сначала посмотрим на следующую схему:

Предположим, сцена, нам нужно, чтобы A отображалась поверх B, а затем добавить движущуюся анимацию к B, возникнет логическая проблема: B продвигается на уровень композиции из-за анимации, и, наконец, изображение на экране синтезируется на GPU, А нужно отображать поверх Б, никакой обработки мы не делаем. Итак, чтобы A и B отображались нормально, нам нужно установить z-index. В это время браузер заставит A быть составным слоем, а затем перерисовать.

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

4. Факторы, влияющие на композит

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

  1. 3D-преобразования: translate3d, translateZ и т. д.;
  2. такие элементы, как видео, холст, iframe;
  3. Анимированные переходы непрозрачности через Element.animate();
  4. Анимированные переходы непрозрачности с помощью CSS-анимации;
  5. position: fixed;
  6. will-change;
  7. filter;
  8. Есть потомки синтетического слоя и само переполнение не видно (если сам SelfPaintingLayer сгенерирован явным фактором позиционирования, z-индекс должен быть не автоматическим)
    так далее…

Вот лишь некоторые примеры,Оптимизация производительности беспроводной сети: КомпозитныйЭта статья описывает это очень подробно, поэтому я не буду вдаваться в подробности здесь.

5. Сжатие слоев и взрыв слоев

1. Сжатие слоя:
Подобные примеры нашего синтетического слоя, неявно упомянутые, могут просто перекрываться, будут производить большие объемы синтетического слоя, это займет много невинных ресурсов ЦП и памяти, что серьезно повлияет на производительность страницы. Этот браузер также учитывается, поэтому будет слой обработки сжатия (Layer Squashing).

Автоматическое сжатие слоев в браузере не является всемогущим: во многих конкретных случаях браузер не может выполнять сжатие слоев.


Как показано ниже, и это ситуации, которых мы должны стараться избегать:

  • Сжатие, нарушающее порядок рендеринга, невозможно
  • Слой рендеринга элемента видео не может быть сжат, а другие слои рендеринга не могут быть сжаты на слой компоновки, где находится видео.
  • Слой рендеринга iframe и плагина не может быть сжат, а другие слои рендеринга не могут быть сжаты до составного слоя, на котором он расположен.
  • Невозможно сжать слои рендеринга с атрибутом отражения (squashingReflectionDisallowed).
  • Невозможно сжать слои рендеринга с атрибутом режима наложения (squashingBlendingDisallowed).
  • Когда слой рендеринга имеет контейнер отсечения, отличный от слоя композиции, слой рендеринга не может быть сжат (squashingClippingContainerMismatch).
  • Слои рендеринга, прокручиваемые относительно слоев компоновки, не могут быть сжаты (scrollsWithRespectToSquashingLayer).
  • Когда слой рендеринга и слой композитинга имеют разные слои-предки с непрозрачностью (один с заданной непрозрачностью и меньше 1, а другой без непрозрачности, который также отличается), слой рендеринга не может быть сжат (squashingOpacityAncestorMismatch, то же, что и squashingClippingContainerMismatch).
  • Когда слой рендеринга имеет другой предок с преобразованием, чем слой композиции, слой рендеринга не может быть сжат (squashingTransformAncestorMismatch, там же).
  • Когда слой рендеринга имеет другой слой-предок с фильтром из слоя компоновки, слой рендеринга не может быть сжат (squashingFilterAncestorMismatch, там же).
  • Когда слой наложения композиции выполняет анимацию, слой рендеринга не может быть сжат (squashingLayerIsAnimating), а слой рендеринга может быть сжат только тогда, когда анимация еще не запущена или завершилась.

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

Если несколько слоев рендеринга перекрываются со слоем композиции, слои рендеринга сжимаются в один GraphicsLayer, чтобы предотвратить возможный «взрыв слоя» из-за перекрытия.

2. Взрыв слоя:
Из предыдущего введения мы знаем, что перекрытие со слоем композиции также продвигает элемент на слой композиции.Хотя в браузере существует механизм сжатия слоев, во многих случаях сжатие выполнить невозможно. Другими словами, в дополнение к нашим явно объявленным составным слоям некоторые неожиданные составные слои могут быть непреднамеренно сгенерированы из-за перекрывающихся причин, и в экстремальной точке может быть создано большое количество дополнительных составных слоев, что приводит к явлению слоя. взрыв.

Чтобы решить проблему взрыва слоя, лучшее решение — нарушить условие перекрытия, то есть позволить другим элементам не перекрываться с элементами слоя композиции, например, разумное использование атрибута z-index.

6. Потребление памяти

Как упоминалось выше, процесс синтеза слоя будет генерировать потребление памяти, поэтому, как мы оцениваем память, потребляемую слоем, проиллюстрирует следующий пример:

<!-- jartto test -->
<div id="a"></div>
<div id="b"></div>

#a, #b {
 will-change: transform;
}
#a {
 width: 100px;
 height: 100px;
 background: rgb(255, 0, 0);
}
#b {
 width: 10px;
 height: 10px;
 background: rgb(255, 0, 0);
 transform: scale(10);
}

Как и выше, мы создали два контейнера #a и #b, физический размер #a составляет 100×100 пикселей (100×100×3 = 30000 байт), а #b — всего 10×10 пикселей (10×10×3 = 300 байт). байт), но увеличенный в 10 раз. #b Анимация преобразования будет отображать слой через графический процессор благодаря свойству will-change.

Мы получаем количество пикселей в изображении, умножая высоту изображения на ширину изображения. Затем умножаем на 3, так как каждый пиксель описывается тремя байтами (RGB). Тогда нетрудно понять, что если изображение содержит прозрачные области, мы умножаем на 4, потому что для описания прозрачности нужны дополнительные байты: (RGBA): 100×100×4 = 40000 байт.

Из приведенного выше примера мы делаем очень содержательный вывод, который помогает нам провести несколько простых оптимизаций. Например: если вы хотите анимировать большое изображение, вы можете загрузить уменьшенную версию (10% от оригинала), а затем увеличить масштаб. Это незаметно для пользователя, но мы упростили загрузку страницы, чтобы улучшить взаимодействие с пользователем.

7. Перекомпоновка и перекраска

Очень хорошо, мы можем оценить потребление памяти через вышеизложенное, вот два термина Reflow и Repaint, краткий обзор:

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

Reflow занимает больше времени, чем Repaint, что больше влияет на производительность. Поэтому при написании кода старайтесь избегать слишком большого количества Reflow.

Причина перепрошивки:

  • Когда страница инициализируется;
  • При манипулировании DOM;
  • Изменился размер некоторых элементов;
  • Если свойства CSS изменились.

Уменьшить оплавление/перерисовку

  • Не изменяйте стили DOM один за другим. Вместо этого лучше предварительно определить класс css, а затем изменить имя класса DOM.
  • Не помещайте значения свойств узлов DOM в цикл как переменные в цикле.
  • Используя фиксированную или абсолютную позицию для анимированных HTML-элементов, изменение их CSS не приведет к перекомпоновке.
  • Никогда не используйте схему таблицы. Потому что небольшое изменение может привести к перестановке всей таблицы.

8. Аппаратное ускорение

Поскольку весь процесс рендеринга занимает очень много времени, легко понять, что большинству людей нравится использовать translateZ(0) и они будут изменять аппаратное ускорение.

Повернувшись, я вернулся к теме этой статьи: к слою композиции. Лучший способ повысить уровень композиции — использовать свойство CSS will-change. И изменение значения непрозрачности, преобразования, верхнего, левого, нижнего, правого может продвигать элемент на слой композиции.

Давайте посмотрим на поддержку браузером will-change,Нажмите, чтобы просмотреть
will-change
Общая поддержка довольно хорошая, поэтому мы можем использовать ее следующим образом:

#jartto {
  will-change: transform;
}

Конечно, для отдельных неподдерживаемых браузеров мы используем translateZ(0) для решения,Нажмите, чтобы просмотреть
translate

#jartto {
  transform: translateZ(0);
}

We already know that animation of transform and opacity via CSS transitions or animations automatically creates a compositing layer and works on the GPU.

Итак, вопрос в том, аппаратное ускорение зависит от GPU, и почему GPU быстрее, чем CPU, давайте посмотрим дальше.

Девять, CPU (центральный процессор) и GPU (графический процессор)

В статье неоднократно упоминаются CPU и GPU.Полагаю, что у многих ботов могут возникнуть такие сомнения: зачем включать аппаратное ускорение и в чем преимущества GPU?

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

  • рисовать каждый составной слой как отдельное изображение;
  • Подготовьте данные слоя (размеры, смещения, прозрачность и т. д.);
  • Подготовить анимационные шейдеры (если применимо);
  • отправить данные на GPU;

отpu-accelerated-compositing-in-chromeКак видно из этой статьи, у аппаратного синтеза есть три преимущества:

  1. Составление слоев на графических процессорах может обеспечить более высокую эффективность, чем на центральных процессорах (как с точки зрения скорости, так и энергопотребления) при рисовании и комбинировании операций с участием большого количества пикселей. Аппаратное обеспечение предназначено для этих типов рабочих нагрузок.
  2. Контент на графическом процессоре не требует дорогостоящих считываний (например, ускоренное видео Canvas2D или WebGL).
  3. Параллелизм между ЦП и ГП, который может работать одновременно для создания эффективных графических конвейеров.

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

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

Дополнительные сведения о графическом процессоре см. здесь.портал, тут не далеко.

10. Дополнение: Обязанности CPU и GPU

Здесь я добавлю еще одну вещь:

Можно сказать, что работа, выполняемая ЦП, выполняется на программном уровне, а ГП — на аппаратном уровне, мы можем делать что угодно с программным обеспечением (используя ЦП), но для обработки изображений обычно быстрее использовать аппаратное обеспечение, поскольку ГП использует пары изображений для быть высокопараллельными Операции с плавающей запятой оптимизированы.

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

  1. ЦП вычисляет отображаемое содержимое и передает его графическому процессору.
  2. Поместите результат рендеринга в буфер кадра после завершения рендеринга GPU.
  3. Видеоконтроллер будет считывать данные кадрового буфера построчно по сигналу VSync и передавать их на дисплей после возможного цифро-аналогового преобразования.

Мы видим, что GPU действительно силен, но лучше не бросать все на GPU, проблема в том, что GPU не имеет неограниченной производительности обработки, и как только ресурсы будут израсходованы, производительность начнет снижаться (даже если ЦП занят не полностью). На самом деле у них есть свои обязанности.

11. Использование инструментов

Мы не вступаем в неподготовленные бои и рационально используем инструменты, чтобы значительно повысить эффективность программирования. Рекомендовать статью здесьОптимизация анимации карты Gaode, содержание включает:

  • Проверка работоспособности страницы
  • Отладчик анимации Chrome (анимации)
  • Отрисовка страницы
  • Слои
  • GPU и составные слои

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

12. Предложения по оптимизации

Вкратце, переход на композитный слой имеет следующие преимущества:

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

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

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

Итак, вы понимаете, вот почему мы используем второй метод вместо первого:

/*jartto:方式一*/
@keyframes move {
 from { left: 30px; }
 to { left: 100px; }
}

/*jartto:方式二*/
@keyframes move {
 from { transform: translateX(0); }
 to { transform: translateX(70px); }
}

13. Резюме

Оптимизация — это на самом деле процесс, с которым нужно разбираться и разбирать по пунктам. Ничто не достигается за одну ночь, и нет такой вещи, как серебряная пуля. Точно так же, как об ошибке сказано в школьном учебнике по физике: «Ошибка неизбежна, и ее можно только уменьшить».

То же самое относится и к оптимизации, мы можем только стараться изо всех сил, а не принуждать. Продолжай пытаться, Клык вечен.

Ссылаться на:
Оптимизация производительности беспроводной сети: Композитный
CSS GPU Animation
совокупность веб-оптимизации
рендеринг в браузере
gpu-accelerated-compositing-in-chrome
Просмотр причин рендеринга, зависания процессора и графического процессора и решений по их оптимизации