人们已经注意到 Firefox 速度又回来了。
在过去七个月里,我们一直在快速替换引擎的主要部分,将 Rust 和 Servo 的部分引入 Firefox。此外,我们还成立了一个浏览器性能突击队,对代码库进行全面搜索,寻找明显和不明显的性能问题。
我们称之为量子项目,重生后的 Firefox Quantum 的第一个通用版本将于明天发布。
但这并不意味着我们的工作已经完成。也不意味着今天的 Firefox 已经达到了它所能达到的速度和响应速度。
所以,让我们看看 Firefox 如何重获速度以及未来将如何变得更快。
通过粗粒度并行性打下基础
为了变得更快,我们需要利用过去 10 年硬件发生的变化。
我们并不是第一个这样做的人。Chrome 在首次推出时就比 Firefox 更快、更具响应性。其中一个原因是 Chrome 工程师看到了硬件正在发生变化,他们开始更好地利用这些新硬件。
一种新的 CPU 样式开始流行起来。这些 CPU 具有多个内核,这意味着它们可以独立地执行任务,但同时也可以并行执行。
但这可能很棘手。在并行的情况下,您可能会引入难以发现和难以调试的细微错误。例如,如果两个内核需要将内存中的同一个数字加 1,如果您没有特别小心,其中一个可能会覆盖另一个。
避免此类错误的一个非常直接的方法是确保您正在处理的两个东西不必共享内存——将您的程序拆分为无需过多合作的相当大的任务。这就是粗粒度并行性。
在浏览器中,很容易找到这些粗粒度。将每个标签页视为单独的工作部分。网页周围也有东西——浏览器 chrome——这些可以单独处理。
这样,页面可以以自己的速度同时工作,而不会相互阻塞。如果您在后台标签页中有一个长时间运行的脚本,它不会阻塞前台标签页中的工作。
这是 Chrome 工程师预见到的机会。我们也看到了这一点,但我们走的路更坎坷。由于我们有一个现有的代码库,我们需要规划如何拆分该代码库以利用多个内核。
这花了一些时间,但我们最终实现了。通过 Electrolysis 项目,我们最终将多进程设置为所有用户的默认设置。Quantum 通过其他一些项目使我们对粗粒度并行性的利用更加出色。
电解
电解为量子项目奠定了基础。它引入了与 Chrome 引入的类似的多进程架构。由于这是一个很大的变化,我们在 2016 年开始对一小部分用户进行测试,然后在 2017 年年中将其推广到所有 Firefox 用户,从而逐步引入它。
量子合成器
量子合成器将合成器移到了自己的进程中。这里最大的优势是使 Firefox 更加稳定。拥有一个单独的进程意味着如果图形驱动程序崩溃,它不会使整个 Firefox 崩溃。但拥有这个单独的进程也使 Firefox 更加响应。
量子 DOM
即使您在内核之间拆分内容窗口,并为每个内容窗口提供一个单独的主线程,主线程仍然需要完成很多任务。其中一些比其他任务更重要。例如,响应按键比运行垃圾回收更重要。量子 DOM 为我们提供了一种优先处理这些任务的方法。这使得 Firefox 更具响应性。大部分工作已经完成,但我们仍然计划通过名为抢占式调度的方式进一步推进。
通过细粒度并行性最大限度地利用硬件
但是,当我们展望未来时,我们需要比粗粒度并行性走得更远。
粗粒度并行性可以更好地利用硬件……但它无法最大限度地利用硬件。当您在不同的内核之间拆分这些网页时,其中一些网页没有工作要做。因此这些内核将处于空闲状态。同时,在一个新内核上启动一个新页面需要的时间与 CPU 为单内核时一样长。
能够使用所有这些内核来处理正在加载的新页面会很棒。然后您就可以更快地完成这些工作。
但是,在粗粒度并行性中,您无法从一个内核中分离出任何工作发送到其他内核。工作之间没有边界。
使用细粒度并行性,您可以将这个更大的任务分解成更小的单元,然后将其发送到不同的内核。例如,如果您有类似 Pinterest 网站的东西,您可以将不同的固定项目拆分,然后发送到不同的内核进行处理。
这不仅有助于解决粗粒度并行性带来的延迟问题。它还有助于提高纯粹的速度。页面加载速度更快,因为工作分布在所有内核之间。随着您添加更多内核,您的页面加载速度会随着内核数量的增加而不断加快。
所以我们看到这是未来,但如何实现还不完全清楚。因为要使这种细粒度并行性变快,您通常需要在内核之间共享内存。但这样会产生 我之前提到的那些数据竞争。
但我们知道浏览器必须进行这种转变,所以我们开始投资研究。我们创建了一种没有这些数据竞争的语言——Rust。然后我们创建了一个浏览器引擎——Servo——它充分利用了这种细粒度并行性。通过此,我们证明了这可以实现,并且您实际上可以在速度更快的情况下减少错误。
量子 CSS(又名 Stylo)
使用 Stylo,CSS 样式计算工作完全并行地分布在所有 CPU 内核之间。Stylo 使用一种称为工作窃取的技术来有效地在内核之间拆分工作,以便所有内核都能保持忙碌。通过这样做,您将获得线性加速。您将 CSS 样式计算所需的时间除以内核数量。
量子渲染(采用 WebRender)
硬件的另一个高度并行化的部分是 GPU。它有数百个或数千个内核。但是,您需要进行大量规划才能确保这些内核尽可能保持忙碌。这就是 WebRender 的作用。
WebRender 将在 2018 年发布,并将利用现代 GPU。同时,我们也从另一个角度解决了这个问题。高级层项目修改了 Firefox 现有的层系统以支持批量渲染。它通过优化 Firefox 当前的 GPU 使用模式,为我们带来了立竿见影的效果。
???
我们认为渲染管道的其他部分也可以从这种细粒度并行性中受益。在接下来的几个月里,我们将仔细研究在哪里还可以使用这些技术。
确保我们不断变得更快,永远不会变慢
除了我们知道必须进行的这些重大架构变更之外,许多性能错误也偷偷地潜入了代码库,而我们却毫不知情。
所以我们创建了量子的另一个部分来解决这个问题……基本上是一个浏览器性能突击队,负责寻找这些问题并动员团队进行修复。
量子流
量子流团队就是这个突击队。他们不是专注于特定子系统的整体性能,而是专注于一些非常具体、重要的用例——例如加载您的社交媒体 feed——并跨团队合作,找出为什么它在 Firefox 中的响应速度不如其他浏览器。
量子流为我们带来了许多重大的性能提升。在此过程中,我们还开发了工具和流程,使查找和跟踪这些类型的问题变得更加容易。
那么量子流现在会怎样呢?
我们正在将这个非常成功的过程——一次识别和专注于一个关键用例——转变为我们工作流程的常规部分。为此,我们正在改进我们的工具,以便我们不再需要一支专家突击队来搜索问题,而是可以赋予更多工程师在整个组织中找到问题的能力。
但这项方法有一个问题。当我们优化一个用例时,可能会使另一个用例退化。为了防止这种情况发生,我们正在添加许多新的跟踪功能,包括改进 CI 自动化运行性能测试、跟踪用户体验的遥测以及错误内部的回归管理。有了这些,我们预计 Firefox Quantum 将会不断改进。
明天仅仅是个开始
明天对我们 Mozilla 来说是个重要日子。过去一年我们一直在努力让 Firefox 更快,但这仅仅是个开始。
在未来的一年里,我们将不断推出新的性能改进,我们期待与您分享!
尝试 Firefox Quantum 正式版 或者 开发者版,以确保您在更新发布时第一时间获取最新版本。
关于 Lin Clark
Lin 在 Mozilla 的高级开发部门工作,专注于 Rust 和 WebAssembly。
82 条评论