RenderingNG

为新一代 Web 内容做好准备

Chris Harrelson
Chris Harrelson

RenderingNG 是一种新一代渲染架构,其性能远远优于之前的架构。RenderingNG 历经 8 年多的时间打造而成,代表了许多 Chromium 开发者的集体成果。它可以充分发挥 Web 内容的巨大潜力,让内容快速、流畅、可靠、响应迅速且富有互动性。

RenderingNG 的不同元素的草图
RenderingNG

在本课程中,您将了解我们构建了什么、为何构建这些产品以及它们的运作方式。

北极星目标

促使 RenderingNG 的北极星目标是,浏览器引擎实现及其渲染 API 的丰富性不应成为 Web 用户体验的限制因素。

您不必担心浏览器 bug 会导致功能不可靠或破坏网站的呈现。

不应出现神秘的性能下降。 而且,您不应需要绕过缺少的内置功能。

应该可以正常运行。

RenderingNG 是朝着这一北极星目标迈出的一大步。在 RenderingNG 之前,我们可以(并且确实)添加渲染功能并提升性能,但很难让这些功能对开发者可靠,并且存在许多性能断崖。现在,我们采用了一种架构,可以系统地解决其中的许多问题,还可以解锁之前被认为不可行的高级功能。其中包括:

  • 在不同平台、设备和操作系统组合中拥有坚实可靠的核心功能。
  • 具有可预测且可靠的性能。
  • 最大限度地使用硬件功能(核心、GPU、屏幕分辨率、刷新率、低级别光栅 API)。
  • 仅执行显示可见内容所需的工作。
  • 内置支持常见的视觉设计、动画和互动设计模式。
  • 提供开发者 API,以便轻松管理渲染费用。
  • 为开发者插件提供渲染管道扩展点。
  • 优化所有内容,包括 HTML、CSS、2D 画布、3D 画布、图片、视频和字体。

与其他浏览器渲染引擎的比较

Gecko 和 WebKit 也实现了这些博文中所述的大部分相同架构功能,在某些情况下,甚至比 Chromium 更早就添加了这些功能。

任何浏览器变得更快、更可靠都是值得庆祝的,而且会产生实际影响。最终目标是提升所有浏览器的基准,以便开发者能够依赖它。

成功金字塔

我的理念是,成功是先实现可靠性、然后实现可伸缩性能,最后实现可扩展性所带来的结果。

金字塔图,底部标签为“可靠性”,中间标签为“性能”,顶部标签为“可扩展性”

与现实生活中的金字塔一样,每个层级都为上一层级提供了坚实的基础。

可靠性

一张草图,展示了如何使用 RenderingNG 添加功能,而不会大幅增加用户的挫败感

要想提供丰富而复杂的用户体验,首先需要一个坚如磐石的平台。核心功能和基础架构必须正常运行,并能够长期运行。同样重要的是,这些功能必须能够很好地组合,并且没有奇怪的边界情况行为或 bug。

草图:添加功能、获取反馈、提高可靠性是循环往复的过程

因此,可靠性是 RenderingNG 最重要的部分。可靠性是良好测试、优质反馈环、指标和软件设计模式的结果。

为了让大家了解我认为可靠性有多重要,我们在过去八年的大部分时间都花在了解决这一问题上。首先,我们深入了解了该系统,从 bug 报告中了解了薄弱环节并加以修复,引导了全面测试,并了解了网站的性能需求以及 Chromium 性能的限制。然后,我们仔细地逐步设计并推出了关键的设计模式和数据结构。 只有这样,我们才能添加真正面向自适应设计、可伸缩性和渲染自定义的下一代基元。

草图图表:可靠性、性能和可扩展性随时间推移而不断提升

这并不是说,在这段时间内 Chromium 没有任何改进。事实恰恰相反!在这些年里,我们逐步重构并推出了各项改进,可靠性和性能也稳步提升。

测试和指标

在过去 8 年中,我们添加了数万项单元测试、性能测试和集成测试。此外,我们还开发了全面的指标,用于衡量 Chromium 在本地测试、性能基准测试以及真实用户和设备在真实网站上的使用场景中呈现的渲染行为的诸多方面。

不过,无论 RenderingNG(或其他浏览器的渲染引擎)有多出色,如果浏览器之间存在大量 bug 或行为差异,Web 开发仍然不会很容易。为此,我们还会尽可能使用Web 平台测试。每项测试都验证 Web 平台的一种使用模式,所有浏览器都应力求通过这些测试。我们还会密切监控相关指标,以便随着时间的推移通过更多测试提高核心兼容性

网络平台测试是多方协作完成的。例如,Chromium 工程师仅添加了 CSS 功能总 WPT 测试量的约 10%;其他浏览器供应商、独立贡献者和规范作者贡献了其余部分。打造可互操作的 Web 需要举全村之力!

在不同引擎中通过的测试
通过 wpt.fyi/compat2021 衡量核心功能的 WPT 通过率

良好的软件设计模式

反过来,如果代码易于理解,并且设计方式可最大限度地降低出现 bug 的可能性,那么可靠地交付优质软件就会变得更加容易。我们将在后续博文中详细介绍 RenderingNG 的软件设计。

可扩缩的性能

在速度、内存和功耗等方面实现出色的性能是 RenderingNG 的下一个重要方面。我们希望与所有网站的互动都能顺畅且响应迅速,同时又不会牺牲设备的稳定性。

但我们不仅仅追求性能,我们还追求可伸缩的性能,即在低端和高端机器以及各种操作系统平台上都能可靠地提供出色性能的架构。我将其称为“扩容”(充分利用硬件设备可实现的所有功能),以及“缩容”(在需要时最大限度提高效率并降低系统需求)。

为此,我们需要最大限度地利用缓存、性能隔离和 GPU 硬件加速。我们来逐一了解一下。为了更具体地说明这一点,我们来思考一下,每种方法如何提升网页上一种非常重要的互动(滚动)的性能。

缓存

在动态、交互式界面平台(例如 Web)中,缓存是显著提升性能的最重要的方式。浏览器中最常见的缓存类型是 HTTP 缓存,但呈现也有许多缓存。滚动最重要的缓存是缓存的 GPU 纹理和显示列表,它们可让滚动速度极快,同时最大限度地减少电池耗电,并在各种设备上正常运行。

缓存有助于延长电池续航时间并提高滚动动画帧速率,但更重要的是,它可以解除对主线程的性能隔离。

性能隔离

在新型桌面计算机上,您不必担心后台应用会拖慢您正在使用的应用的速度。这是因为抢占式多任务处理,这是一种性能隔离形式:确保独立任务不会相互拖慢。

在 Web 上,性能隔离的最佳示例是滚动。 即使在包含大量运行缓慢的 JavaScript 的网站上,滚动也能非常流畅,因为它是在不必依赖 JavaScript 和布局线程的其他线程中运行的。我们在 RenderingNG 上投入了大量精力,通过缓存(不仅限于显示列表,还涵盖更复杂的情况)来确保所有可能的滚动都采用线程化处理。例如,用于表示固定位置和固定到顶部元素的代码、被动事件监听器和高质量文本渲染。

Sketch 显示,使用 RenderingNG 时,即使 JavaScript 运行速度非常慢,性能也能保持稳定。

GPU 加速

GPU 可显著加快生成像素和绘制到屏幕的速度。在许多情况下,每个像素都可以与其他每个像素并行绘制,从而显著提高速度。RenderingNG 的一个关键组成部分是 GPU 光栅和随处绘制。 这会在所有平台和所有设备上使用 GPU,以极大地加速 Web 内容的渲染和动画效果。这在低端设备或极高端设备上尤为重要,因为这类设备的 GPU 通常比设备的其他部分要强大得多。

Sketch 显示,使用 RenderingNG 时性能不会下降太多。

可扩展性:合适的工具

在确保可靠性和可伸缩性能后,我们现在可以利用一系列工具来帮助开发者扩展 HTML、CSS 和 Canvas 的内置部分,并且不会牺牲任何来之不易的性能和可靠性。

其中包括内置 API 和 JavaScript 公开 API,适用于响应式设计、渐进渲染、流畅度和响应速度以及线程渲染等高级用例。

以下由 Chromium 倡导的开放 Web API 得益于 RenderingNG,而之前被认为不可行。

所有这些功能都是根据开放规范开发的,并与开放 Web 合作伙伴(其他浏览器的工程师、专家和 Web 开发者)合作开发的。在后续的博文中,我们将深入探讨这些功能,并说明 RenderingNG 如何实现这些功能。

  • content-visibility:让网站能够轻松避免为屏幕外内容执行渲染工作,并缓存当前未显示的单页应用视图的渲染内容。
  • OffscreenCanvas:允许 Canvas 渲染(2D Canvas API 和 WebGL)在自己的线程中运行,以实现可靠的卓越性能。该项目也是 Web 的又一个重要里程碑,它是第一个允许 JavaScript(或 WebAssembly!)通过多个线程渲染单个网页文档的 Web API。
  • 容器查询:允许单个组件以响应式方式进行布局,从而解锁整个插拔即用组件世界(目前处于实验性实现阶段)。
  • 源站隔离:允许网站选择在 iframe 之间实现更强的性能隔离。
  • 主线程以外的绘制工作流:让开发者能够通过在合成器线程上运行的代码来扩展元素的绘制方式。

除了显式 Web API 之外,RenderingNG 还让我们能够发布多项对所有网站都有益的非常重要的“自动功能”:

  • 网站隔离:将跨源 iframe 放入不同的 CPU 进程中,以实现更好的安全性和性能隔离。
  • VulkanD3D12Metal:利用比 OpenGL 更高效地使用 GPU 的低级 API。
  • 更多合成动画:SVG、背景颜色。

RenderingNG 解锁的其他即将推出的功能包括:

构成 RenderingNG 的主要项目

下面列出了 RenderingNG 中的关键项目。

CompositeAfterPaint

CompositeAfterPaint 会将合成与样式、布局和绘制分离,从而显著提高可靠性和可预测的性能、提高吞吐量,并在不牺牲性能的情况下减少内存用量。

进度
2015 发布显示列表。
2017 发布了新的失效功能。
2018 船舶属性树第 1 部分。
2019 船舶属性树(第 2 部分)。
2021 已完成项目发货。

LayoutNG

从头开始重写了所有布局算法,大大提高了可靠性并使性能更可预测。

详细了解 LayoutNG

进度
2019 发货区块流程。
2020 正在编辑 Ship Flex。
2021 寄送所有其他物品。

BlinkNG

我们重构并清理了 Blink 渲染引擎,将其分解为清晰分隔的流水线阶段。这样可以实现更好的缓存、更高的可靠性,以及内容可见性和容器查询等可重入或延迟渲染功能。

全面支持 GPU 加速

GPU 加速可为大多数内容带来巨大的速度提升,因为每个像素都可以并行处理。这也是提高低端设备(通常仍具有 GPU)性能的有效方法。

进度
2014 支持画布。在 Android 上针对用户选择接受的内容提供。
2016 在 Mac 上发货。
2017 超过 60% 的 Android 网页浏览会使用 GPU。
2018 在 Windows、ChromeOS 和 Android Go 上发布。
2019 线程化 GPU 光栅化。
2020 分发其余 Android 内容。

线程滚动、动画和解码

我们长期致力于将所有滚动、非布局诱导动画和图片解码从主线程移出。该计划正在实施中。

进度
2011 初步支持线程滚动和动画。
2015 图层压缩。
2016 通用溢出滚动。
2017 在 compositor 线程中解码图片。
2018 在 compositor 线程中执行图片动画。
2020 始终复合固定位置。
2021 百分比转换动画、SVG 动画。

Viz

一种集中式光栅和绘制进程,可提高吞吐量、优化内存并允许最佳利用硬件功能。它还有一些其他优势,Web 开发者可能不太明显,但对用户来说非常明显,例如取消屏蔽网站隔离功能,以及将渲染流水线与浏览器界面渲染分离。

进度
2018 OOP-R 已在 Android、Mac 和 Windows 上发布。
2019 OOP-D 已发货。OOP-R 在所有国家/地区(画布除外)均有销售。在 Linux 上发布了 SkiaRenderer。
2020 在 Windows 和 Android 上发布了 SkiaRenderer。Android 上发布了 Vulkan。
2021 SkiaRenderer 已在 Mac 上发布(ChromeOS 版即将发布)。

上表中术语的定义:

OOP-D
进程外显示合成器。 显示合成与操作系统合成器是同一类活动。外部进程是指在 Viz 进程中执行此操作,而不是在网页的渲染进程或浏览器界面进程中执行。
OOP-R
进程外光栅。光栅正在将显示列表转换为像素。 外部进程是指在可视化进程中执行此操作,而不是在网页的呈现进程中执行。
SkiaRenderer
一种新的显示屏合成程序实现,可支持在各种不同的底层 GPU API(例如 Vulkan、D3D12 或 Metal)上执行。

线程化和加速的画布渲染

正是这个项目让 OffscreenCanvas 成为可能。

进度
2018 发布 OffscreenCanvas。
2019 发布 ImageBitmapRenderingContext。
2021 采用 OOP-R 方式发货。

VideoNG

VideoNG 是一项长期的努力,旨在提供高效、可靠且高质量的 Web 视频播放。

进度
2014 引入了基于 Mojo 的渲染框架。
2015 提供了 Project Butter 和视频叠加层,以实现更流畅的视频渲染。
2016 发布了统一的 Android 和桌面解码和渲染流水线。
2017 已发布 HDR 和色彩校正视频渲染。
2018 发布了基于 Mojo 的视频解码流水线。
2019 已发布基于 Surface 的视频渲染流水线。
2021 在 ChromeOS 上提供了4K 受保护内容呈现支持。

上表中术语的定义:

Mojo
适用于 Chromium 的新一代 IPC 子系统。
Surface
一种概念,是可视化项目设计的一部分。

插图:Una Kravets。