содержание
1. Анализ анимационных катонов
Причина зависания анимации
Частота обновления большинства устройств составляет 60 раз/сек, т.е. 1-секундный ролик даже из 60 картинок генерируется вместе, поэтому требования браузера к рендерингу каждого кадра должны выполняться за 16 мс. Когда время рендеринга превышает 16 мс, на 1 секунду меньше, чем 60 генераций экрана, не будет когерентного ощущения Катона, влияющего на работу пользователя.
процесс рендеринга страницы
Рендеринг фрейма страницы на клиенте делится на следующие этапы:
-
JavaScript
: JavaScript реализует анимационные эффекты, манипулирование DOM и т. д. -
Style(样式计算)
: Подтверждает правила стиля CSS, применяемые к каждому элементу DOM. -
Layout(布局)
: вычисляет окончательный размер и положение каждого элемента DOM на экране. Так как компоновка DOM-элементов относительна, когда элемент меняется и влияет на компоновку, другие элементы тоже будут меняться, и его нужно откатывать и перерисовывать.Этот процесс называется перекомпоновкой. -
Paint(绘制)
: рисует текст, цвета, изображения, границы, тени и т. д. элементов DOM на нескольких слоях. -
Composite(Render Layer合并)
: объединение слоев в логическом порядке и отображение их на экране.
Когда браузер фактически отображает страницу, ему необходимо пройти ряд сопоставлений, от дерева DOM, созданного HTML-страницей, до последнего слоя Процесс сопоставления выглядит следующим образом (источник:Ссылка [3]) (обратите внимание, что имена классов на следующем рисунке позже были изменены, RenderObject->LayoutObject, RenderLayer->PaintLayer):
- Node->RenderObject: каждый узел дерева DOM имеет соответствующий RenderObject (отношение один к одному, RenderObject содержит содержимое узла);
-
RenderObject -> RenderLayer: Один или несколько RenderObjects соответствуют RenderLayer (многие к одному). RenderLayer используется для обеспечения иерархической связи между элементами. Вообще говоря, элементы, расположенные в одном месте и на одном уровне, находятся в одном и том же Render Layer. Только какой-то специальный RenderObject Новый слой рендеринга создается специально, а другие RenderObjects совместно используют один с первым элементом-предком, имеющим RenderLayer. Общий RenderObject, который генерирует RenderLayer, имеет одну из следующих характеристик.Ссылка [3]:
- корневой элемент страницы
- Имеет свойства позиционирования CSS (относительное, абсолютное, фиксированное, липкое)
- прозрачный не 1
- перелив не виден
- Имеет свойство маски CSS
- Имеет свойство CSS box-reflect
- Имеет свойство фильтра CSS
- Элемент 2D-холста с 3D- или аппаратным ускорением
- видео элемент
-
RenderLayer -> GraphicsLayer: один или несколько RenderLayer соответствуют GraphicsLayer (многие к одному), некоторые RenderLayer, которые считаются составляющими слоями, соответствуют только GraphicsLayer, а другие RenderLayer делят GraphicsLayer с первым элементом-предком, имеющим GraphicsLayer. Каждый GraphicsLayer имеет GraphicsContext для рисования соответствующих RenderLayers, а компоновщик синтезирует растровое изображение GraphicsContexts и, наконец, отображает его на экране. Слои рендеринга повышаются до слоев композитинга по следующим причинам:
- Имеет свойство 3D-преобразования
- Имеет атрибут перспективы
- 3D-холст или 2D-холст с аппаратным ускорением
- Элементы iframe с аппаратным ускорением (например, страница, встроенная в iframe, имеет слой композитинга, а слой композитинга требует аппаратного ускорения)
- Используйте плагины с аппаратным ускорением, такие как flash
- Применена анимация/переход к свойствам непрозрачности/преобразования (когда анимация/переход активна)
- Дочерний элемент — это композитный слой.
- Родственный элемент — это композитный слой, который перекрывается с текущим не компостирующим слоем, и его уровень ниже, чем текущий слой.
- Имеет атрибут изменения
2. Метод оптимизации
В Интернете можно увидеть множество кратких описаний схем оптимизации, и большие ребята их хорошо написали.
Talk is cheap. Show me the code.
В сочетании с процессом рендеринга страницы здесь будут объединены некоторые тестовые коды для анализа различных схем оптимизации и эффектов анимации:
-
JavaScript
: оптимизировать эффективность выполнения JavaScript.-
requestAnimationFrame
заменятьsetTimeout
а такжеsetInterval
- Параллелизуемые обновления элементов DOM, разделенные на несколько небольших задач.
- DOM-независимые трудоемкие операции помещаются в
Web Workers
середина
-
-
Style
: Уменьшить вычислительную сложность и область применения стиля.- Уменьшена сложность селекторов стилей.
- Уменьшите количество элементов, которым необходимо выполнять расчеты стилей.
-
Layout
: избегайте больших и сложных макетов.- Избегайте частых изменений макета
- Замените старую модель макета макетом flexbox.
- Избегайте форсирования синхронных событий макета
-
Paint/Composite
: ускорение графического процессора- Перемещение движущихся или градиентных элементов из слоя RenderLayer в составной слой.
- Избегайте ловушек повышения уровня композиции
JavaScript
: оптимизировать эффективность выполнения JavaScript.
1. requestAnimationFrame
заменятьsetTimeout
а такжеsetInterval
ЗачемsetTimeout
а такжеsetInterval
нехорошо?
Так как js выполняется в одном потоке, чтобы предотвратить блокировку процесса из-за длительного времени выполнения определенной задачи, в js существует концепция асинхронной очереди.setTimeout
а такжеajax
Все запросы помещаются в асинхронную очередь, а задачи в асинхронной очереди выполняются, когда основной процесс пуст. такsetTimeout
а такжеsetInterval
Время выполнения функции обратного вызова не может быть гарантировано. Она может выполняться несколько раз в одном кадре, что приводит к рендерингу нескольких страниц, напрасной трате ресурсов ЦП или даже к задержке, или выполняться, когда кадр подходит к концу, вызывая повторную визуализацию и выпадение кадров..
requestAnimationFrame
Как это оптимизировано?
- Энергосбережение процессора, приостановка рендеринга, когда страница скрыта или свернута.
- Функция регулирования, интервал цикла которой определяется частотой обновления экрана, гарантирует, что функция обратного вызова выполняется только один раз в каждом интервале обновления экрана.
Каков эффект оптимизации?DEMO
Просмотрите разницу в конкретной производительности через панель производительности Chrome.
пройти черезsetTimeout
Есть 3 рендера и есть длинные кадры:
использоватьrequestAnimationFrame
Части манипулирования DOM объединены, выполняется только 2 рендера, а также оптимизированы длинные кадры:
2. DOM-независимые трудоемкие операции помещаются вWeb Worker
середина
Web Worker
Каковы преимущества?
JavaScript является однопоточным. Если часто выполнять трудоемкие операции (например, обновление данных в режиме реального времени), это вызовет перегрузку и повлияет на взаимодействие с пользователем.Web Worker
Функция состоит в том, чтобы создать многопоточную среду для JavaScript.Рабочий поток работает в фоновом режиме и контролируется основным потоком, и они не мешают друг другу. Рабочий поток отвечает за задачи с высокой задержкой и независимые от пользовательского интерфейса задачи, а основной поток отвечает за взаимодействие с пользовательским интерфейсом, которое будет относительно плавным.
требует внимания
-
Web Worker
DOM нельзя манипулировать, и по сути это просто отдельное выполнение обновления данных и рендеринга страницы. -
Web Worker
Следуйте политике того же источника и ограничьте локальный доступ. - Обмен дополнительным сетевым запросом и ресурсами потока браузера для эффективного выполнения.
Каков эффект оптимизации?DEMO
Вы можете просмотреть разницу в конкретной производительности через панель производительности Chrome:
Не используйтеweb worker
, сетевой запрос уменьшается, но фрейм длинный, и есть риск зависания фрейма.
использовалweb worker
После этого задачи, не связанные с трудоемкими операциями, больше не блокируются, а увеличивают задержку в сети. Если вы используете воркеров в своем проекте, необходимо тщательно продумать время инициализации.
Возможные сценарии применения
- Опрос сервер, чтобы получить данные
- Частые отчеты о данных
- Длительная обработка данных
Style
: Уменьшить вычислительную сложность и область применения стиля.
1. Уменьшить сложность селекторов стиля?
Уменьшение сложности селекторов стилей — часто предлагаемый метод оптимизации, но на самом деле эффект от этого метода относительно слабый, согласно статье Ивана Курича.[5]Метод испытания (DEMO), на странице с 50 000 узлов влияние различной сложности селектора на производительность не превысит 20 мс, и в целом количество узлов на странице не будет достигать этого числа.
Причина слабого эффекта оптимизации в том, что движок браузера оптимизирует скорость работы селектора, а разные движки имеют разные схемы оптимизации производительности, поэтому трудно предсказать, эффективна ли оптимизация разработчика, по крайней мере, для оптимизации статики. элементы, стоимость производительности чрезвычайно низка.
Одна вещь, которая может быть подтверждена тестированием, заключается в том, что она должна бытьУменьшите использование селекторов псевдоклассов и длинных селекторов.. Рекомендуется организовывать CSS в соответствии с соглашениями об именах, такими как OOCSS и BEM, преимущество которых заключается в небольшой оптимизации производительности и улучшении удобства сопровождения кода.
2. Уменьшите количество элементов, которым необходимо выполнять расчеты стилей.
Это для старых браузеров, если старые браузеры изменилисьbody
Класс элемента, все его дочерние элементы должны пересчитывать стиль.
Современные браузеры оптимизированы, поэтому эффект оптимизации зависит от конкретного сценария приложения. Примеры приложений пока не раскопаны, и если они будут найдены позже, они будут заполнены.
Layout
: избегайте больших и сложных макетов.
1. Избегайте частых триггеров макета
Стоимость рендеринга, вызванная разными свойствами, различна, что особенно очевидно при анимации css. Свойства анимации, запускающие компоновку или отрисовку, особенно требовательны к производительности, поэтому их следует использовать как можно чаще.transform
а такжеopacity
В качестве свойства анимации, если это невозможно, рассмотрите возможность реализации анимации в JavaScript.
Насколько велика разница в производительности?Возьмите ширину и преобразование в качестве примера, чтобы понять разницу в производительности анимации соответственно:DEMO
Анимация реализована по ширине, частота кадров низкая, дрожание кривых очевидно.В правом нижнем углу также показан процесс рендеринга одного кадра, который запускает расчет стиля, верстку, отрисовку и слияние слоев рендеринга:
Для достижения анимации с помощью преобразования можно обнаружить, что частота кадров низкая, но стабильная, а процесс рендеринга запускает только расчет стиля и слияние слоев рисования и рендеринга (только когда элемент является составным слоем, рисование не будет запускаться. Подробно о нем будет рассказано позже):
2. Замена старой модели компоновки на флексбокс-макет
Обычно используемые классические схемы макета включают макет на основе плавающего положения и макет на основе абсолютного позиционирования, макет Flexbox более эффективен. В проектах, которые можно выкладывать с помощью flexbox, попробуйте использовать flexbox для вёрстки. последующийDEMOПопробуйте рендуринг того же интерфейса с тремя макетами для проверки производительности:
Для каждого элемента требуется абсолютная планировка: уникальные координаты позиционирования необходимы для каждого элемента. Когда есть много элементов, файл CSS слишком велик, что приводит к большему количеству времени на расчет стиля.
Плавающий макет: расположение плавающих элементов будет влиять друг на друга, а на некоторые плавающие элементы также влияет поток документа, что приводит к увеличению времени макета.
Гибкая компоновка: по сравнению с первыми двумя схемами компоновки производительность значительно улучшена.
3. Избегайте событий принудительной синхронизации макета
Что такое макет принудительной синхронизации?
Как упоминалось ранее, процесс рендеринга страницы — это JavaScript->Стиль->Макет->Рисование->Композит.Принудительное синхронное размещение — это принудительное выполнение браузером макета перед выполнением скрипта JavaScript.
Что может вызвать принудительную синхронную компоновку?
Когда JavaScript запущен, полученный стиль атрибута элемента является значением предыдущего кадра, поэтому, если в процессе рендеринга текущего кадра элемент модифицируется до получения атрибута текущего кадра, браузер должен сначала применить его Затем атрибут выполняет логику JavaScript.Короче говоря, DOM сначала записывается, а затем читается, особенно непрерывные операции чтения и записи, которые оказывают большее влияние на производительность браузера.Насколько велико влияние на производительность?DEMO
DEMO тестирует влияние событий макета принудительной синхронизации на производительность, изменяя свойства 1000 узлов, как показано на следующем рисунке. Можно обнаружить, что потеря производительности огромна.Непрерывные операции чтения и записи вызывают непрерывные принудительные события синхронизации, и время выполнения JavaScript становится очень большим:
Paint/Composite
: ускорение графического процессора
1. Переместите движущиеся или градиентные элементы из RenderLayer в составной слой.
Примечание. Вы можете просмотреть составной слой на панели слоев инструментов разработчика Chrome.Панель слоев открывается командой+shift+p(mac)/ctrl+shift+p(windows) -> показать слоиВыдвигайте сложные/часто меняющиеся элементы на композиционный слой, преимущество этого в том, что когда элемент рисуется, он не запускает рисование других элементов. Причины, по которым слой рендеринга повышается до составного слоя, следующие (обратите внимание, что следующие причины основаны на слое рендеринга):
- Имеет свойство 3D-преобразования
- Имеет атрибут перспективы
- 3D-холст или 2D-холст с аппаратным ускорением
- Элементы iframe с аппаратным ускорением (например, страница, встроенная в iframe, имеет слой композитинга, а слой композитинга требует аппаратного ускорения)
- Плагины, использующие аппаратное ускорение, такие как flash/iframe
- Применена анимация/переход к свойствам непрозрачности/преобразования (когда анимация/переход активна)
- изменяемые свойства: непрозрачность, преобразование, верх, лево, низ, право
- Дочерний элемент — это композитный слой.
- Родственный элемент — это составной слой, который перекрывается с текущим некомпостирующим слоем.Уровень компостирующего слоя ниже уровня некомпостирующего слоя.
Почему есть прирост производительности?
- Перерисовывать только те части, которые необходимо перерисовать
- Ускорение графического процессора: растровое изображение слоя композиции напрямую синтезируется графическим процессором, что быстрее, чем обработка ЦП.
Насколько улучшилась производительность? DEMOКак видно из демонстрации, после перехода на синтетический слой время, необходимое для покраски, значительно сокращается.
Не лучше ли увеличить количество слоев синтеза?
Видно, что после поднятия композитного слоя время покраски значительно сокращается. Однако создание композиционного слоя требует дополнительной памяти и ресурсов управления.Слишком много композиционных слоев увеличивает нагрузку на страницу.DEMOБыло создано 5000 элементов, все они были переведены в составной слой, чтобы сравнить потребление памяти, когда они не были повышены. Это особенно важно для мобильных устройств, по сравнению с ПК ресурсы памяти мобильных устройств более напряжены.
Поднимите только слой рендеринга анимированного элемента
Основываясь на принципе обновления до составного слоя для повышения производительности, когда другие части страницы сложны и относительно статичны, мы можем рассмотреть возможность обновления элементов анимации до составного слоя по отдельности, чтобы уменьшить влияние элементов анимации на другие элементы страницы. страница.
2. Избегайте ловушек при повышении уровня композиции
Вспомним последнюю причину повышения до компостирующего слоя: родственным элементом является композитный слой, который перекрывается с текущим некомпостирующим слоем, а компостирующий слой находится ниже по уровню, чем некомпостирующий слой.
Полученный приподнятый композиционный слой обычно является неожиданным. Причина связана с процессом рендеринга экрана.Вспомним последний шаг сопоставления страниц.Каждому композитному слою соответствует растровое изображение.Композитор окончательно объединяет эти растровые изображения в соответствии с иерархическими отношениями и, наконец, выводит их на экран. На данный момент мы предполагаем, что A — это известный композитный слой, а B в идеале должен быть обычным слоем рендеринга, и его иерархическая взаимосвязь показана на рисунке:
Как обычный слой рендеринга, B находится в том же растровом изображении, что и родительский элемент, а A находится в отдельном растровом изображении.В это время будут проблемы с уровнем при слиянии.Если B находится непосредственно поверх A, это может привести к тому, что уровень будет ниже, чем вместо этого, родительский элемент A's B отображается поверх A. Напротив, иерархическая связь между A и B неверна. Решение браузера в настоящее время состоит в том, чтобы визуализировать B отдельно как слой композиции, что приводит к неожиданному созданию слоя композиции.
В это время первый инстинкт — избегать дублирования, верно? Однако все не так просто. В поисках информации я нашел покемона-assumedOverlap. Буквальное значение состоит в том, чтобы предположить перекрытие.Для некоторых элементов, которые невозможно/трудно определить, будут ли они перекрываться со слоем композитинга, браузер предполагает, что перекрытие произойдет, и продвигается к слою композитинга.
Этот браузер также был оптимизирован, и благодаря процессу сжатия слоев (Layer Squashing) слои рендеринга, которые перекрываются с составным слоем и объединяются в один составной слой, объединяются. Чтобы предотвратить взрыв слоя, вызванный слишком большим количеством подъемных слоев синтеза, вызванным перекрытием, см.DEMO.
Тем не менее, все еще есть ситуации, которые не могут быть решены сжатием слоев, см.исходный кодМожно перечислить следующие причины (обратите внимание, что все они основаны на предпосылке перекрытия/гипотетического перекрытия):
-
scrollsWithRespectToSquashingLayer
: слой рендеринга прокручивается относительно слоя сжатия.Когда прокручиваемый слой рендеринга перекрывает слой композитинга, будет создан новый слой композитинга, который не может быть сжат.DEMO (этот пример не очень, codepen встроен в iframe, весь iframe стал составным слоем, если хотите увидеть эффект, то можете посмотреть его локально) -
squashingSparsityExceeded
: Сжатие слоя рендеринга приведет к тому, что сжатый слой будет слишком разреженным.DEMO -
squashingClippingContainerMismatch
: Контейнеры клипов слоя рендеринга и слоя сжатия различны.Простое понимание состоит в том, что типы переполнения контейнера перекрывающихся слоев рендеринга различны.DEMO -
squashingOpacityAncestorMismatch
: свойство непрозрачности, унаследованное от предка, отличается для слоя визуализации и слоя сжатия.DEMO -
squashingTransformAncestorMismatch
: слой рендеринга и слой сжатия имеют разные преобразования, унаследованные от предков.DEMO -
squashingFilterAncestorMismatch
: Слой рендеринга и слой сжатия имеют разные атрибуты фильтра, унаследованные от предков, или сам слой рендеринга имеет атрибут фильтра.DEMO -
squashingWouldBreakPaintOrder
: Невозможно сжать без нарушения порядка рендеринга (например, родительский элемент имеет атрибут маски/фильтра, дочерний элемент перекрывается со сжатым слоем, в случае слияния атрибут маски/фильтра родительского элемента не может быть локально применен к слою сжатия, что приводит к неправильному результату рендеринга) .DEMO -
squashingVideoIsDisallowed
: элемент видео не может быть сжат.DEMO -
squashedLayerClipsCompositingDescendants
: когда композитный слой является обрезанным дочерним, перекрывающийся слой рендеринга не может быть сжат.DEMO -
squashingLayoutPartIsDisallowed
: Не удалось сжать фрейм/iframe/плагин. -
squashingReflectionDisallowed
: невозможно сжать слои рендеринга со свойствами отражения.DEMO -
squashingBlendingDisallowed
: невозможно сжать слои рендеринга с атрибутом режима наложения.DEMO -
squashingNearestFixedPositionMismatch
: Ближайший фиксированный элемент слоя рендеринга, в отличие от слоя сжатия, не может быть сжат.DEMO
Когда они находят содержимое страницы, но ясно, что нет ничего больше карт, когда вы можете проверить, это не причина, это дает следующий общий уровень сжатия, который не может решить ситуацию:
- пояс
transform
Анимированный элемент, за которым следует элементrelative/absolute
позиция
Причина: как относительный элемент, так и абсолютный элемент под относительным продвигаются к составному слою из-за предполагаемого перекрытия и из-за настройки переполнения: скрытый на основе вышеупомянутогоsquashingClippingContainerMismatch
, контейнер отсечения слоя рендеринга отличается от контейнера составного слоя, что приводит к невозможности сжатия слоя и появлению слишком большого количества составных слоев.
Обходной путь: установить для анимированных элементовz-index
Нарушить порядок композитного слоя.DEMO
три,Ссылаться на
Структура этой статьи в основном относится к статье [1], а некоторые моменты оптимизации действительно проверены и расширены, что можно расценивать как ощущение после прочтения~
Со сжатием слоев ситуация слишком сложная, никакой информации я не нашел, и чувствую, что не до конца разобрался, позже будет возможность переделать. Спасибо следующим ребятам!
- Углубленный анализ принципа производительности браузерного рендеринга, насколько вы его знаете?woo woo Краткое описание.com/afraid/ah 32 no 890 from 2…
- Optimizing CSS: ID Selectors and Other Myths woohoo.site point.com/optimizing-…
- GPU Accelerated Compositing in Chrome woohoo.chromium.org/developers/…
- Что такое ускорение графического процессораBump.IO/notes/2017/…
- Blink Compositing Update: Recap and Squashing docs.Google.com/present Вопрос А…
- Оптимизация производительности беспроводной сети: КомпозитныйТаобао Fed.org/blog/2016/0…
Конец цветкаПриветственный совет
коммерческое время
Feishu — это офисный пакет ByteDance, который глубоко интегрирует такие функции, как мгновенная связь, совместная работа в Интернете, аудио- и видеоконференции, календарь, облачный диск и рабочее место, чтобы предоставить пользователям универсальные возможности для совместной работы. В настоящее время клиенты услуг Feishu охватывают многие области, такие как Интернет-технологии, информационные технологии, производство, строительство и недвижимость, корпоративные услуги, образование и средства массовой информации. Добро пожаловать в команду ByteDance Feishu, существует большое количество front-end и back-end HC ~ отсканируйте QR-код или нажмите на ссылку для доставки, ищите команду Feishu👍~
【Набор в школу】Внутренний push-код: HZNVPHS, ссылка для доставки:job.toutiao.com/s/JaeUCoc
【Социальный набор】Ссылка для доставки:job.toutiao.com/s/JaevUNo