Здесь вы узнаете, как настраиваются компоненты RenderingNG и как через них проходит конвейер рендеринга.
Начиная с самого высокого уровня, задачами рендеринга являются:
- Преобразуйте содержимое в пиксели на экране.
- Анимируйте визуальные эффекты содержимого из одного состояния в другое.
- Прокрутка в ответ на ввод.
- Эффективно направляйте вводимые данные в нужные места, чтобы сценарии разработчика и другие подсистемы могли реагировать.
Содержимое для рендеринга — это дерево фреймов для каждой вкладки браузера, а также интерфейс браузера. И поток необработанных событий ввода с сенсорных экранов, мышей, клавиатур и других аппаратных устройств.
Каждый кадр включает в себя:
- Состояние DOM
- CSS
- Холсты
- Внешние ресурсы, такие как изображения, видео, шрифты и SVG.
Фрейм — это HTML-документ плюс его URL-адрес. Веб-страница, загруженная на вкладку браузера, имеет фрейм верхнего уровня, дочерние фреймы для каждого iframe, включенного в документ верхнего уровня, и их рекурсивные потомки iframe.
Визуальный эффект — это графическая операция, применяемая к растровому изображению, например прокрутка, преобразование, обрезка, фильтрация, непрозрачность или смешивание.
Компоненты архитектуры
В RenderingNG эти задачи логически разделены на несколько этапов и компонентов кода. Компоненты попадают в различные процессы ЦП, потоки и подкомпоненты внутри этих потоков. Каждый из них играет важную роль в достижении надежности , масштабируемой производительности и расширяемости всего веб-контента.
Рендеринг структуры конвейера
Рендеринг происходит в конвейере с множеством этапов и артефактов, создаваемых на этом пути. Каждый этап представляет собой код, выполняющий одну четко определенную задачу в рамках рендеринга. Артефакты — это структуры данных , которые являются входными или выходными данными этапов.
Этапы:
- Анимация: изменяйте вычисленные стили и деревья свойств с течением времени на основе декларативных временных шкал.
- Стиль: примените CSS к DOM и создайте вычисляемые стили .
- Макет: определите размер и положение элементов DOM на экране и создайте неизменяемое дерево фрагментов .
- Предварительная раскраска: вычислите деревья свойств и при необходимости аннулируйте любые существующие списки отображения и плитки текстур графического процессора.
- Прокрутка: обновление смещения прокрутки документов и прокручиваемых элементов DOM путем изменения деревьев свойств.
- Paint: вычисляет список отображения, описывающий, как растрировать фрагменты текстур графического процессора из DOM.
- Зафиксировать: скопировать деревья свойств и список отображения в поток компоновщика.
- Layerize: разбейте список отображения на составной список слоев для независимой растеризации и анимации.
- Растровые, декодирующие и рисующие рабочие программы: преобразуйте списки отображения, закодированные изображения и код рабочей программы рисования соответственно в плитки текстур графического процессора .
- Активировать: создайте фрейм композитора , показывающий, как рисовать и размещать фрагменты графического процессора на экране, а также любые визуальные эффекты.
- Агрегировать: объединить кадры компоновщика из всех видимых кадров компоновщика в один глобальный кадр композитора.
- Draw: выполнение агрегированного кадра компоновщика на графическом процессоре для создания пикселей на экране.
Этапы конвейера рендеринга можно пропустить, если они не нужны. Например, анимация визуальных эффектов и прокрутки могут пропускать макет, предварительную прорисовку и прорисовку. Именно поэтому анимация и прокрутка отмечены на схеме желтыми и зелеными точками. Если макет, предварительную отрисовку и отрисовку можно пропустить для визуальных эффектов, их можно полностью запустить в потоке наборщика и пропустить основной поток.
Рендеринг пользовательского интерфейса браузера здесь не показан напрямую, но его можно рассматривать как упрощенную версию того же конвейера (и фактически его реализация использует большую часть кода). Видео (также не изображенное напрямую) обычно визуализируется с помощью независимого кода, который декодирует кадры в фрагменты текстур графического процессора, которые затем подключаются к кадрам компоновщика и на этапе рисования.
Структура процессов и потоков
Процессы ЦП
Использование нескольких процессов ЦП обеспечивает изоляцию производительности и безопасности между сайтами и от состояния браузера, а также изоляцию стабильности и безопасности от оборудования графического процессора.
- Процесс рендеринга визуализирует, анимирует, прокручивает и маршрутизирует ввод для одной комбинации сайта и вкладки. Существует несколько процессов рендеринга.
- Процесс браузера визуализирует, анимирует и маршрутизирует входные данные для пользовательского интерфейса браузера (включая адресную строку, заголовки вкладок и значки), а также направляет все оставшиеся входные данные в соответствующий процесс рендеринга. Есть один процесс браузера.
- Процесс Viz объединяет композиции из нескольких процессов рендеринга, а также процесса браузера. Он растрирует и рисует с помощью графического процессора. Есть один процесс Viz.
Разные сайты всегда подвергаются разным процессам рендеринга.
Несколько вкладок браузера или окон одного и того же сайта обычно выполняются в разных процессах рендеринга, если только вкладки не связаны, например, одна не открывает другую. При сильной нехватке памяти на настольном компьютере Chromium может помещать несколько вкладок с одного и того же сайта в один и тот же процесс рендеринга, даже если они не связаны друг с другом.
В пределах одной вкладки браузера кадры с разных сайтов всегда находятся в разных процессах рендеринга, но кадры с одного и того же сайта всегда находятся в одном и том же процессе рендеринга. С точки зрения рендеринга важным преимуществом нескольких процессов рендеринга является то, что межсайтовые iframe и вкладки обеспечивают изоляцию производительности друг от друга. Кроме того, страны происхождения могут пойти на еще большую изоляцию .
Для всего Chromium существует ровно один процесс Viz, поскольку обычно для рисования используется только один графический процессор и экран.
Выделение Viz в отдельный процесс полезно для стабильности перед лицом ошибок в драйверах графического процессора или оборудовании. Это также хорошо для изоляции безопасности, что важно для API-интерфейсов графических процессоров, таких как Vulkan , и безопасности в целом .
Поскольку в браузере может быть множество вкладок и окон, и во всех из них есть пиксели пользовательского интерфейса браузера, которые нужно отрисовывать, вы можете задаться вопросом: почему существует ровно один процесс браузера? Причина в том, что одновременно фокусируется только один из них; на самом деле, невидимые вкладки браузера в большинстве случаев деактивируются и освобождают всю память графического процессора. Однако сложные функции рендеринга пользовательского интерфейса браузера все чаще реализуются и в процессах рендеринга (известных как WebUI ). Это делается не из соображений изоляции производительности, а для того, чтобы воспользоваться простотой использования механизма веб-рендеринга Chromium.
На старых устройствах Android процессы рендеринга и браузера являются общими при использовании в WebView (в целом это не относится к Chromium на Android, только к WebView). В WebView процесс браузера также используется совместно с приложением для внедрения, а WebView имеет только один процесс рендеринга.
Иногда также существует служебный процесс для декодирования защищенного видеоконтента. Этот процесс не изображен на предыдущих диаграммах.
Темы
Потоки помогают добиться изоляции производительности и скорости реагирования, несмотря на медленные задачи, распараллеливание конвейеров и множественную буферизацию.
- В основном потоке выполняются сценарии, цикл событий рендеринга, жизненный цикл документа, проверка попадания, диспетчеризация событий сценария и анализ HTML, CSS и других форматов данных.
- Помощники основного потока выполняют такие задачи, как создание растровых изображений и больших двоичных объектов, требующих кодирования или декодирования.
- Веб-работники запускают скрипт и цикл событий рендеринга для OffscreenCanvas.
- Поток Compositor обрабатывает входные события, выполняет прокрутку и анимацию веб-контента, вычисляет оптимальную слоистость веб-контента и координирует декодирование изображений, рабочие программы рисования и растровые задачи.
- Помощники потоков компоновщика координируют растровые задачи Viz, выполняют задачи декодирования изображений, рабочие программы рисования и резервный растр.
- Потоки вывода мультимедиа, демультиплексора или звука декодируют, обрабатывают и синхронизируют видео- и аудиопотоки. (Помните, что видео выполняется параллельно с основным конвейером рендеринга.)
Разделение основного потока и потока композитора критически важно для изоляции производительности анимации и прокрутки от работы основного потока.
Для каждого процесса рендеринга существует только один основной поток, хотя несколько вкладок или фреймов с одного и того же сайта могут оказаться в одном процессе. Однако производительность изолирована от работы, выполняемой в различных API браузера. Например, создание растровых изображений и больших двоичных объектов в Canvas API выполняется во вспомогательном потоке основного потока.
Аналогично, для каждого процесса рендеринга существует только один поток композитора. Обычно не проблема, что он только один, потому что все действительно дорогостоящие операции в потоке компоновщика делегируются либо рабочим потокам компоновщика, либо процессу Viz, и эта работа может выполняться параллельно с маршрутизацией ввода, прокруткой или анимацией. . Рабочие потоки Compositor координируют задачи, выполняемые в процессе Viz, но ускорение графического процессора повсюду может не работать по причинам, не зависящим от Chromium, например, из-за ошибок драйверов. В таких ситуациях рабочий поток будет выполнять работу в резервном режиме на ЦП.
Количество рабочих потоков композитора зависит от возможностей устройства. Например, настольные компьютеры обычно используют больше потоков, поскольку они имеют больше ядер ЦП и менее ограничены по заряду батареи, чем мобильные устройства. Это пример увеличения и уменьшения масштаба .
Архитектура потоков процесса рендеринга представляет собой применение трёх различных шаблонов оптимизации:
- Вспомогательные потоки : отправьте долго выполняющиеся подзадачи в дополнительные потоки, чтобы родительский поток реагировал на другие одновременные запросы. Хорошими примерами этого метода являются вспомогательные потоки основного потока и вспомогательные потоки композитора.
- Множественная буферизация : отображать ранее обработанный контент при рендеринге нового контента, чтобы скрыть задержку рендеринга. Поток наборщика использует эту технику.
- Распараллеливание конвейера: запуск конвейера рендеринга в нескольких местах одновременно. Вот как прокрутка и анимация могут быть быстрыми; даже если происходит обновление рендеринга основного потока, прокрутка и анимация могут выполняться параллельно.
Процесс браузера
- Поток рендеринга и композитинга реагирует на вводимые данные в пользовательском интерфейсе браузера, направляет другие входные данные в правильный процесс рендеринга; макетирует и рисует пользовательский интерфейс браузера.
- Помощники потоков рендеринга и компоновки выполняют задачи декодирования изображений и резервного растра или декодирования.
Процесс рендеринга браузера и поток композиции аналогичны коду и функциональности процесса рендеринга, за исключением того, что основной поток и поток компоновщика объединены в один. В этом случае необходим только один поток, поскольку нет необходимости в изоляции производительности от длинных задач основного потока, поскольку их нет по замыслу.
а именно процесс
- Растровые изображения основного потока графического процессора отображают списки и видеокадры в виде фрагментов текстур графического процессора и рисуют кадры компоновщика на экране.
- Поток компоновщика дисплея объединяет и оптимизирует компоновку каждого процесса рендеринга, а также процесса браузера, в единый кадр компоновщика для представления на экране.
Растр и рисование обычно выполняются в одном и том же потоке, поскольку оба они полагаются на ресурсы графического процессора, и трудно надежно использовать многопоточный графический процессор (более простой многопоточный доступ к графическому процессору является одной из причин разработки нового стандарта Vulkan). ). В Android WebView существует отдельный поток рендеринга на уровне ОС для рисования, поскольку WebViews встроены в собственное приложение. На других платформах, вероятно, появится такая тема в будущем.
Компоновщик дисплея находится в другом потоке, поскольку он должен всегда реагировать и не блокировать любой возможный источник замедления в основном потоке графического процессора. Одной из причин замедления основного потока графического процессора являются вызовы кода, не относящегося к Chromium, например драйверов графического процессора конкретного поставщика, которые могут быть медленными в труднопредсказуемых случаях.
Структура компонента
Внутри каждого основного потока или потока композитора процесса рендеринга имеются логические программные компоненты, которые структурированным образом взаимодействуют друг с другом.
Компоненты основного потока процесса рендеринга
В Blink Renderer:
- Фрагмент дерева локальных кадров представляет дерево локальных кадров и DOM внутри кадров.
- Компонент API DOM и Canvas содержит реализации всех этих API.
- Средство выполнения жизненного цикла документа выполняет этапы конвейера рендеринга вплоть до этапа фиксации.
- Компонент тестирования и диспетчеризации входных событий выполняет тесты на попадание, чтобы определить, на какой элемент DOM нацелено событие, а также запускает алгоритмы диспетчеризации входных событий и поведение по умолчанию.
Планировщик и исполнитель цикла событий рендеринга решают, что и когда запускать в цикле событий. Он планирует рендеринг с частотой, соответствующей дисплею устройства.
Фрагменты локального дерева фреймов немного сложны. Напомним, что дерево фреймов — это главная страница и ее дочерние iframe, рекурсивно. Кадр является локальным для процесса рендеринга, если он визуализируется в этом процессе, в противном случае он является удаленным.
Вы можете представить себе раскрашивание кадров в зависимости от процесса их рендеринга. На предыдущем изображении зеленые кружки — это все кадры одного процесса рендеринга; оранжевые — через секунду, а синие — через треть.
Фрагмент локального дерева фреймов — это связный компонент одного цвета в дереве фреймов. На изображении имеется четыре дерева локальных фреймов: два для сайта A, один для сайта B и один для сайта C. Каждое дерево локальных фреймов получает свой собственный компонент рендеринга Blink. Средство рендеринга Blink локального дерева кадров может находиться в том же процессе рендеринга, что и другие локальные деревья кадров, а может и не находиться в нем. Это определяется способом выбора процессов рендеринга, как описано ранее.
Структура потока компоновщика процесса рендеринга
Компоненты композитора процесса рендеринга включают в себя:
- Обработчик данных , который поддерживает составной список слоев, списки отображения и деревья свойств.
- Средство выполнения жизненного цикла , которое выполняет этапы анимации, прокрутки, компоновки, растра, а также декодирования и активации конвейера рендеринга. (Помните, что анимация и прокрутка могут выполняться как в основном потоке, так и в композиторе.)
- Обработчик ввода и проверки попадания выполняет обработку ввода и тестирование попадания с разрешением составных слоев, чтобы определить, можно ли запускать жесты прокрутки в потоке компоновщика и на какой процесс рендеринга следует ориентироваться при проверке попадания.
Пример архитектуры на практике
В этом примере есть три вкладки:
Вкладка 1: foo.com
<html>
<iframe id=one src="foo.com/other-url"></iframe>
<iframe id=two src="bar.com"></iframe>
</html>
Вкладка 2: bar.com
<html>
…
</html>
Вкладка 3: baz.com html <html> … </html>
Структура процессов, потоков и компонентов для этих вкладок выглядит следующим образом:
Давайте рассмотрим по одному примеру каждой из четырех основных задач рендеринга. Напоминание:
- Преобразуйте содержимое в пиксели на экране.
- Анимируйте визуальные эффекты содержимого из одного состояния в другое.
- Прокрутка в ответ на ввод.
- Эффективно направляйте вводимые данные в нужные места, чтобы сценарии разработчика и другие подсистемы могли реагировать.
Чтобы отобразить измененный DOM для первой вкладки:
- Сценарий разработчика изменяет DOM в процессе рендеринга для foo.com.
- Средство рендеринга Blink сообщает композитору, что ему необходим рендеринг.
- Компоновщик сообщает Viz, что для этого требуется рендеринг.
- Viz сигнализирует композитору о начале рендеринга.
- Компоновщик пересылает стартовый сигнал на рендерер Blink.
- Обработчик цикла событий основного потока запускает жизненный цикл документа.
- Основной поток отправляет результат в поток компоновщика.
- Обработчик цикла событий компоновщика запускает жизненный цикл компоновки.
- Любые растровые задачи отправляются в Виз для растра (часто таких задач несколько).
- Viz растровый контент на графическом процессоре.
- Виз подтверждает завершение растровой задачи. Примечание. Chromium часто не ждет завершения растра, а вместо этого использует так называемый токен синхронизации , который должен быть разрешен растровыми задачами перед выполнением шага 15.
- Кадр наборщика отправляется в Viz.
- Viz объединяет кадры композитора для процесса рендеринга foo.com, процесса рендеринга iframe bar.com и пользовательского интерфейса браузера.
- Виз планирует ничью.
- Viz рисует агрегированный кадр композитора на экране.
Чтобы анимировать переход преобразования CSS на второй вкладке:
- Поток композитора для процесса рендеринга bar.com отмечает анимацию в своем цикле событий композитора, изменяя существующие деревья свойств. Затем повторно запускается жизненный цикл композитора. (Могут возникнуть задачи растра и декодирования, но они здесь не описаны.)
- Кадр наборщика отправляется в Viz.
- Viz объединяет кадры композитора для процесса рендеринга foo.com, процесса рендеринга bar.com и пользовательского интерфейса браузера.
- Виз планирует ничью.
- Viz рисует агрегированный кадр композитора на экране.
Чтобы прокрутить веб-страницу на третьей вкладке:
- В процесс браузера поступает последовательность событий
input
(мышь, касание или клавиатура). - Каждое событие направляется в поток композитора процесса рендеринга baz.com.
- Компоновщик определяет, нужно ли основному потоку знать о событии.
- Событие при необходимости отправляется в основной поток.
- Основной поток запускает прослушиватели
input
событий (pointerdown
,touchstar
,pointermove
,touchmove
wheel
), чтобы узнать, будут ли прослушиватели вызыватьpreventDefault
для этого события. - Основной поток возвращает информацию о том, вызывался ли
preventDefault
для компоновщика. - Если нет, событие ввода отправляется обратно в процесс браузера.
- Процесс браузера преобразует его в жест прокрутки, комбинируя его с другими недавними событиями.
- Жест прокрутки снова отправляется в поток композитора процесса рендеринга baz.com.
- Там применяется прокрутка, и поток композитора для процесса рендеринга bar.com отмечает анимацию в своем цикле событий композитора. Затем это изменяет смещение прокрутки в деревьях свойств и повторно запускает жизненный цикл компоновщика. Он также сообщает основному потоку запустить событие
scroll
(здесь не показано). - Кадр наборщика отправляется в Viz.
- Viz объединяет кадры композитора для процесса рендеринга foo.com, процесса рендеринга bar.com и пользовательского интерфейса браузера.
- Виз планирует ничью.
- Viz рисует агрегированный кадр композитора на экране.
Чтобы перенаправить событие click
по гиперссылке в iframe #two на первой вкладке:
- В процесс браузера поступает событие
input
(мышь, касание или клавиатура). Он выполняет приблизительную проверку попадания, чтобы определить, что процесс рендеринга iframe bar.com должен получить щелчок, и отправляет его туда. - Поток композитора bar.com направляет событие
click
в основной поток bar.com и планирует задачу цикла событий рендеринга для его обработки. - Обработчик входных событий для основного потока bar.com проверяет попадание, чтобы определить, какой элемент DOM в iframe был нажат, и запускает событие
click
для наблюдения скриптами. УслышавpreventDefault
, он переходит к гиперссылке. - При загрузке целевой страницы гиперссылки новое состояние отображается с помощью шагов, аналогичных предыдущему примеру «отображение измененного DOM». (Эти последующие изменения здесь не показаны.)
Еда на вынос
Чтобы запомнить и усвоить, как работает рендеринг, может потребоваться много времени.
Самый важный вывод заключается в том, что конвейер рендеринга, благодаря тщательной модульности и вниманию к деталям, был разделен на ряд автономных компонентов. Затем эти компоненты были разделены по параллельным процессам и потокам, чтобы максимизировать масштабируемую производительность и возможности расширения .
Каждый компонент играет решающую роль в обеспечении производительности и функций современных веб-приложений.
Продолжайте читать о ключевых структурах данных , которые так же важны для RenderingNG, как и компоненты кода.
Иллюстрации Уны Кравец.