本文是 RenderingNG 系列文章的第一篇:
-
[译] Chromium 下一代渲染架构(一):RenderingNG
我是 Chris Harrelson,是负责 Blink 渲染的工程主管(渲染是指将 HTML 和 CSS 转换为像素)。八年多来,我一直深入研究 Web 渲染性能,我的个人目标是让 Web 能够更快、更轻松、更可靠地提供出色的用户体验。我很高兴地告诉你,我们这八年来构建了一个新的、尖端的 Chromium 渲染引擎架构。实现这一目标是一项巨大的工程,我希望你喜欢它!
2021 年,我们将基本完成该架构的设计、构建和交付。我们称它为 RenderingNG,它是真正的下一代渲染架构,其性能大大优于以前的架构。RenderingNG 已经进行了至少八年,它代表了 Chromium 开发人员的集体工作成果。它为下一代快速、流畅、可靠、响应迅速和交互式的 Web 释放了巨大的潜力。我相信它也是作为一个基线,定义了开发人员可以依赖的 Web 渲染引擎的新的最低标准。
这篇文章是系列文章中的第一篇,我将解释我们构建了什么、为什么构建它以及它是如何工作的。我会从以下几个方面展开:
- 北极星目标
- 成功金字塔:指导我们工作的原则,以及这些原则在实践中的例子
- RenderingNG 支持的特性和功能
- RenderingNG 主要项目的顶层概述
北极星目标
RenderingNG 的北极星目标是:浏览器引擎的实现及其大量的渲染 API 不能成为 Web 用户体验的限制因素。
你不应该担心浏览器 Bug 会导致浏览器功能不可靠或破坏页面的渲染。
应该没有奇奇怪怪的性能问题。而且,你不需要因为内置功能的缺失做一些 Work Around。
浏览器应该能够保持正常工作。
我相信 RenderingNG 是朝着这个北极星目标迈出的一大步。在 RenderingNG 之前,我们虽然也添加了一些渲染功能并提高了性能,但费了很大力气才让这些功能对开发人员可靠,并且仍然存在许多性能问题。现在我们有了一个新架构,可以系统地解决这些问题,并且还可以支持以前认为不可行的高级功能。RenderingNG 有如下特点:
- 具有跨不同平台、设备和操作系统的坚如磐石的核心功能。
- 具有可预测的、可靠的性能。
- 能最大限度地利用硬件能力(内核、GPU、屏幕分辨率、刷新率、底层栅格化 API)。
- 仅执行显示可见内容所需的工作。
- 内置支持常见的视觉设计、动画和交互设计模式。
- 为开发者提供 API 以轻松管理渲染成本。
- 为开发者插件提供渲染流水线扩展点。
- 优化所有内容 —— HTML、CSS、2D Canvas、3D Canvas、图像、视频和字体。
与其他浏览器渲染引擎的比较
Gecko 和 Webkit 也实现了文章中描述的大部分的架构特性,在某些情况下甚至在 Chromium 之前就添加了它们。这非常棒!任何一种浏览器变得更快和更可靠都是值得庆祝并且具有实际影响的,但最终目标是推进所有浏览器的基线,以便开发人员可以依赖它。
成功金字塔
我的理念是,成功首先要实现可靠性,然后是可伸缩性能,最后是可扩展性。
与现实生活中的金字塔一样,每一层都为上一层提供了必要的坚实基础。
可靠性
如果要实现丰富而复杂的用户体验,我们首先需要的是一个坚如磐石的平台。核心功能和基础必须正常工作,并随着时间的推移继续工作。同样重要的是这些功能组合良好并且没有奇怪的 Edge-Case 或 Bug。
因此,可靠性是 RenderingNG 中最重要的一个部分。可靠性是由良好的测试、质量反馈循环、指标和软件设计模式带来的结果。
为了说明可靠性的重要性,我们在过去八年的大部分时间里都只关注这一个部分。首先,我们对系统建立了深入的了解 —— 从缺陷报告中学习并修复它们,执行全面测试,理解网站的性能需求和 Chromium 性能的限制。然后,我们仔细地逐步设计并推出了关键的设计模式和数据结构。直到那时我们才说为下一代的响应式设计、渲染的可伸缩性能和可扩展性准备好了。
这并不是说 Chromium 在那段时间没有任何改进。事实上,情况正好相反!这些年来,随着我们逐步重构和推出每项改进,可靠性和性能稳步持续提高。
测试和指标
在过去的 8 年中,我们增加了数以万计的单元测试、性能测试和集成测试。此外,我们还开发了全面的指标,用来衡量 Chromium 渲染在本地测试、性能基准测试以及真实站点、真实用户和设备在真实环境中的表现。
但是,无论 RenderingNG(或其他浏览器的渲染引擎)多么出色,如果存在大量错误或浏览器之间的行为差异,那么为 Web 开发仍然不容易。为了解决这个问题,我们还最大限度地利用了 Web Platform Tests。这些测试中的每一个都验证了所有浏览器都应该通过的 Web 平台的使用模式。我们还密切监控随着时间推移通过更多测试和提高核心兼容性的指标。
Web Platform Tests 是一项大家共同协作的工作。例如,Chromium 工程师只为 CSS 的特性添加了大约 10% 的测试;其他浏览器提供商、独立贡献者和规范作者贡献了其余部分。建立相互兼容的 Web 需要大家一起努力!
好的软件设计模式
如果代码易于理解并且设计方式能够最大限度地减少错误的可能性,那么可靠地交付高质量的软件就会容易得多。在后续的文章中,我们将详细介绍 RenderingNG 的软件设计。
可伸缩性能
在速度、内存和功耗方面实现出色的性能是 RenderingNG 下一个最重要的方面。我们希望与所有网站的交互顺畅且响应迅速,但又不牺牲设备的稳定性。
但我们不仅想要性能,我们还想要可伸缩的性能 —— 一种在低端和高端机器上以及跨操作系统平台都能可靠运行的架构。我将其称为 Scaling Up —— 利用硬件设备的所有能力,和 Scaling Down —— 最大化效率并在合适的时候减少对系统的要求。
为了实现这一目标,我们需要最大限度地利用缓存、性能隔离和 GPU 硬件加速,接下来我们一个个来看。为了更具体,我们看一下在网页滚动这个非常重要的交互场景下,这三种手段分别是如何做出贡献的。
缓存
在动态的交互式 UI 平台(例如 Web)中,缓存是显著提高性能的最重要的方法。浏览器中最著名的缓存类型是 HTTP 缓存,但渲染也有许多缓存。滚动场景下最重要的缓存是 GPU 纹理和显示列表的缓存,它们允许滚动非常快,同时最大限度地减少电池消耗并在各种设备上运行良好。
缓存有助于提高电池寿命和动画帧率,但更重要的是它提供了与主线程性能隔离的可能性。
性能隔离
在现代台式计算机上,你永远不必担心后台应用程序会降低你正在工作的应用程序的速度。这是因为抢先式多任务处理,这反过来又是一种性能隔离形式:确保独立任务不会相互拖慢。
在 Web 上,性能隔离的最佳示例是滚动。即使在有很多 JavaScript 慢任务的网站上,滚动也可以非常流畅,因为它运行在不同的线程上,而不必依赖于 JavaScript 和布局线程。我们在 RenderingNG 上投入了大量精力,以确保每个可能的滚动都是线程化的。缓存不止可以优化显示列表,还可以处理更复杂的情况。我们的示例中包括了 fixed 和 sticky 定位的元素、被动事件侦听器和高质量文本渲染。
GPU 加速
GPU 使生成像素和绘制到屏幕的速度显着加快 —— 在许多情况下,每个像素都可以与其他像素并行绘制,从而大大提高了速度。RenderingNG 的一个关键组件是使用 GPU 栅格化和绘制。使用所有平台和所有设备上的 GPU 来加速 Web 内容的渲染和动画。这在低端设备或非常高端的设备上尤其重要,因为它们通常拥有比设备的其他部分更强大的 GPU。
可扩展性:合适的工具
一旦我们拥有了可靠性和可伸缩的性能,我们就可以构建大量工具来帮助开发人员扩展 HTML、CSS 和 Canvas 的能力,并且不会牺牲任何来之不易的性能和可靠性。
这些工具包括用于响应式设计、渐进式渲染、平滑度和响应性以及线程渲染的高级用例的内置 API 和 JavaScript 公开 API。
下面这些由 Chromium 支持的 Web API 是由 RenderingNG 实现的,在 RenderingNG 以前被认为是不可行的。
所有这些都是根据开放的规范和与开放的 Web 合作伙伴(其他浏览器的工程师、专家和 Web 开发者)合作开发的。在后续的文章中,我们将深入探讨其中的每一个,并解释 RenderingNG 如何使它们成为可能。
- content-visibility:允许站点轻松避免渲染屏幕外的内容,并缓存当前未显示的单页应用程序视图的渲染。
- OffscreenCanvas:允许 Canvas(2D Canvas API 和 WebGL)的渲染在自己的线程上运行,以获得可靠的出色性能。这个项目也是 Web 的另一个重要里程碑 —— 它是第一个允许 JavaScript(或 WebAssembly!)从多个线程呈现单个网页文档的 Web API。
- Container queries:允许单个组件以响应方式自行布局,从而让即插即用的组件成为可能(目前是实验性的)。
- Origin isolation:允许网站在 iframe 之间选择更多的性能隔离。
- Off-main-thread paint worklets:为开发人员提供了一种扩展元素绘制方式的方法,让代码在合成器线程上运行。
除了提供 Web API 之外,RenderingNG 还允许我们发布几个非常重要的“自动功能”,这些功能对所有网站都有好处:
- Site Isolation:将跨域 iframe 放在不同的 CPU 进程中,以获得更好的安全性和性能隔离。
- Vulkan、D3D12 和 Metal:比 OpenGL 更有效地使用 GPU 的底层 API。
- 更多合成动画:SVG,背景颜色。
另外,我们对 RenderingNG 即将推出的功能感到兴奋,包括:
- Scroll 动画
- 隐藏但可搜索和可访问的 DOM
- 共享元素转换
- 自定义布局
- 非主线程合成;解耦线程和合成
构成 RenderingNG 的关键项目
以下是 RenderingNG 中的关键项目列表。随后的文章将深入探讨其中的每一个。
CompositeAfterPaint
将合成从样式、布局和绘画中解耦开,从而大大提高了可靠性和可预测的性能,增加了吞吐量,并在不牺牲性能的情况下使用更少的内存。它始于 2014 年,并将于今年(2021年)结束。
| 年份 | 进展 |
|---|---|
| 2015 | 发布显示列表 |
| 2017 | 发布新的失效(原文:Ship new invalidation) |
| 2018 | 发布属性树第 1 部分 |
| 2019 | 发布属性树第 2 部分 |
| 2021 | 发布 SVG |
LayoutNG
彻底重写所有布局算法,大大提高了可靠性和更可预测的性能。它始于2016年,计划于今年(2021年)完成。
| 年份 | 进展 |
|---|---|
| 2019 | 发布 block flow |
| 2020 | 发布 flex, editing |
| 2021 | 发布剩下的所有 |
BlinkNG
将 Blink 渲染引擎进行系统的清理,并重构为干净的分离的多个流水线阶段。这允许更好的缓存、更高的可靠性以及可重入或延迟渲染的功能,例如 Content-Visibility 和 Container Queries 。它始于 2014 年,并逐步改进并一直持续。它将在 2021 年完成。
无处不在的 GPU 加速
我们为了在所有平台上使用 GPU 栅格化、绘图和动画,做了长期的努力。GPU 为大多数内容提供了巨大的加速,因为每个像素都可以并行处理。这也是提高低端设备性能的有效方法,这些设备往往有 GPU。它始于 2014 年,并于 2020 年完成。
| 年份 | 进展 |
|---|---|
| 2014 | Canvas 支持。在 Android 上提供选择性使用 |
| 2016 | 在 Mac 上发布 |
| 2017 | 超过 60% 的 Android 页面浏览使用 GPU |
| 2018 | 在 Windows、ChromeOS 和 Android Go 上发布 |
| 2019 | 线程化的 GPU 栅格化 |
| 2020 | 支持 Android 上其他的内容 |
线程化滚动、动画和解码
将所有滚动、非布局动画和图像解码移出主线程的长期努力。它始于 2011 年,并且一直在进行中。
| 年份 | 进展 |
|---|---|
| 2011 | 对线程化滚动和动画的初始支持 |
| 2015 | 层压缩 |
| 2016 | 通用的 overflow scrolling |
| 2017 | 在合成器线程上进行图像解码 |
| 2018 | 在合成器线程上进行图像动画 |
| 2020 | 始终合成 fixed 定位 |
| 2021 | 百分比 transform 动画,SVG 动画 |
Viz
Viz 是 Chromium 内中心化的负责栅格化和绘图的进程,可以提高吞吐量、优化内存并允许更有效地使用硬件能力。它还具有其他对 Web 开发者来说不太明显但对用户来说非常明显的好处,例如站点隔离和将渲染流水线与浏览器 UI 渲染解耦。它于 2016 年开始,将于 2021 年完成。
| 年 | 进步 |
|---|---|
| 2018 | OOP-R 在 Android、Mac 和 Windows 上发布 |
| 2019 | OOP-D 发布。OOP-R 在其他地方发布(Canvas 除外)。SkiaRenderer 在 Linux 上发布 |
| 2020 | SkiaRenderer 在 Windows 和 Android 上发布。Vulkan 在 Android 上发布。 |
| 2021 | SkiaRenderer 在 Mac 上发布(ChromeOS 上很快也将发布)。 |
上表中的术语定义:
OOP-D(Out Of Process Display compositor)
进程外显示合成。显示的合成与操作系统中合成是同一种活动。进程外意味着在 Viz 进程中执行,而不是在网页的渲染进程或浏览器 UI 进程中执行。
OOP-R(Out Of Process Raster)
进程外栅格化。栅格化就是将显示列表转换为像素。进程外意味着在 Viz 进程而不是网页的渲染进程中执行。
SkiaRenderer
一种新的显示合成器实现,可以支持在一系列不同的底层 GPU API(例如 Vulkan、D3D12 或 Metal)上执行。
线程化和加速 Canvas 渲染
这个项目使 OffscreenCanvas 成为可能。它始于 2015 年,将于 2021 年结束。
| 年份 | 进展 |
|---|---|
| 2018 | 发布 OffscreenCanvas |
| 2019 | 发布 ImageBitmapRenderingContext |
| 2021 | 发布 OOP-R |
VideoNG
该项目长期致力于在网络上提供高效、可靠和高质量的视频播放。
| 年份 | 进展 |
|---|---|
| 2014 | 引入了基于 Mojo 的渲染框架 |
| 2015 | 发布了 Project Butter 和视频叠加层,以实现更流畅的视频渲染 |
| 2016 | 发布统一的 Android 和桌面的解码和渲染流水线 |
| 2017 | 发布 HDR 和色彩校正视频渲染 |
| 2018 | 发布了基于 Mojo 的视频解码流水线 |
| 2019 | 发布了基于 Surface 的视频渲染流水线 |
| 2021 | 在 ChromeOS 上提供 4K 受保护的内容渲染的支持 |
上表中的术语定义:
Mojo
Chromium 的下一代 IPC 子系统。
Surface
Viz 设计中的一个概念。
总结
我对 Web 和 Chromium 上渲染的改进速度感到非常兴奋。我预计未来几年的步伐将继续加快,因为我们能够在 RenderingNG 的坚实基础之上进行构建。
请继续关注更多未来的文章,这些文章将更详细地介绍新架构、它是如何形成的以及它是如何工作的。