在过去的七个月里,我们一直在迅速地更换着引擎的主要部件,在 Firefox 中使用了 Rust 和部分的 Servo。此外,有一个源于代码的问题,明显或不明显的严重影响浏览器性能。
我们称之为“Project Quantum”,重生的首个 Firefox Quantum 常规版本将于明日发布。
但这并不意味着我们的工作已经完成了,也不意味着今后 Firefox 的速度和响应速度不会再有进展。
那么,让我们来看看 Firefox 是如何再次变快的,以及它在哪部分变得更快。
使用 coarse-grained 并行作为基础
为了变得更快,我们要利用在过去 10 年里硬件的变化。
我们并不是第一个这样做的。Chrome 在首次推出时就比 Firefox 更快,响应速度也更快。其中的一个原因就是 Chrome 的工程师看到了硬件的变化,并更好的利用了这一点。
一种新型的 CPU 开始变得流行。这些 CPU 拥有多个核心,这就意味着它们可以独立完成任务,但同时也是并行的。
这可能会变得棘手。使用了 CPU 的并行性,可能会产生一些难以查看且难以调试的细微错误。例如,如果两个核心需要在内存中对同一个数组加一,如果没有足够小心,很容易出现一个将另一个覆盖的问题。
一个很简单的方法去避免这些各种各样的 Bug 就是仅保证两个东西(功能)的运行不会共享内存 —— 在你的程序里把很大的任务拆分为不需要过多(协同)合作(的子任务),这就是粒度并行性。
在浏览器中,可相当容易找到这些粗粒,每一个选项卡都独立地工作。还有围绕该网页的东西 —— Chrome 浏览器 —— 可以独立处理。
这样,页面可以同时工作,而不会互相阻塞。如果在后台选项卡中有长时间运行的脚本,它不会阻塞前台选项卡的工作。
这是 Chrome 工程师所预见的机会,我们也看到了,但是我们实现它的道路更加颠簸。从我们有现存的代码基础,我们需要计划如何拆分代码库,以利用多个内核。
过了段时间,我们实现了它。随着这个“电解”项目的实现,我们最终实现了为所有用户默认启用多进程。量子(浏览器)已经使用粗粒度的并行性,甚至比其他一些项目更好。
电解
“电解”为量子项目奠定了基础,它引入了一种类似于 Chrome 的多进程架构。因为这是一个重大的变化,我们和一小部分用户在 2016 年开始缓慢地引入、测试它,然后在 2017 年年中推送给所有 Firefox 用户。
量子合成器
量子合成器把合成器转移到自己的进程中。这里最大的成功是使得 Firefox 更稳定。有一个单独的进程就意味着一旦图像驱动崩溃,它不仅不会使得所有的 Firefox 的所有页面崩溃,这个独立的进程使得 Firefox 更具响应能力。
Quantum DOM
即使在内核之间拆分内容窗口,并为每个内核分配一个主线程,主线程仍然需要执行很多任务。而其中一些比其他更重要。例如,响应按键比运行垃圾收集更重要。Quantum DOM 为我们提供了一种优先处理这些任务的方法。 这使得 Firefox 更具响应能力。这项工作大部分已经落地,但是我们仍然计划进一步采取一些称作抢先式调度的方法。
充分利用硬件的 fine-grained 并行性
然而,当我们展望未来时,我们需要比 coarse-grained 并行更进一步。
coarse-grained 并行更好地利用了硬件...但并没有充分利用硬件。当你把网页分给不同的内核去做时,有些内核可能就没有被分配到工作。因此这些内核就会闲置下来。与此同时,如果 CPU 是单核的话,由新核心启动新页面的时间就会变得更长。
如果能够使用所有的内核来处理新页面,这将非常好。这样你就可以更快地完成这项工作了。
但是如果使用 coarse-grained 并行,你不能把任何任务从一个内核分离到另一个内核,任务之间是没有界限的。
通过 fine-grained 并行,你可以将一个更大的任务分解成更小的单元以便于发送给不同的内核去处理。例如,如果你有类似于 Pinterest 的网站,你可以把它分成不同的固定模块,将它们发送给不同的内核去处理。
这不仅有助于缓解像粗粒度并行这样的延迟。它也有助于速度的提升。页面会加载得更快,因为计算被分解到了不同的计算内核。随着您添加更多的计算内核,页面会加载越快。
所以我们看到这是未来,但是如何到达那里并不完全清楚。由于要使这种细粒度的并行更快,通常需要在内核之间共享内存。但是这会带来我们之前谈到的那些数据竞争的问题。
但是我们知道浏览器必须做这个转变,所以我们开始投资研究。我们创建了一个没有这些数据竞争问题的语言 —— Rust。然后,我们创建了一个浏览器引擎 —— Servo,以充分利用这种细粒度的并行性。通过这,我们证明了这一点可以发挥作用,并且在加快速度的同时可以减少错误的发生。
Quantum CSS (也称作 Stylo)
使用 Stylo,CSS 样式渲染的工作在所有 CPU 内核中完全并行化。Stylo 使用了一个称为“工作窃取(work stealing)”的技术来高效地分离内核之间的工作,使得每个内核都保持忙碌的状态。通过该技术,会得到一个线性的加速效果。可通过使用拥有的所有内核来为 CSS 的样式渲染分配时间。
Quantum Render (具有 WebRender 特性)
有关硬件的另一部分是可以高度并行的 GPU,它拥有成百上千的内核。即便如此,我们仍然需要确保让 GPU 的多核尽可能地保持工作状态,从而提升效率,这就是 WebRender 所做的工作。
WebRender 计划于 2018 年推出,它将充分利用现代 GPU。同时,我们也从另一个角度来解决这个问题。高级图层项目修改了
Firefox 的现有图层系统以支持批量渲染。通过优化 Firefox 当前的 GPU 使用模式,我们获得了立竿见影的效果。
???
我们认为渲染管道的其他部分也可以从这种细粒度的并行中受益。在接下来的几个月中,我们将仔细研究一下,看看还能在哪些地方使用这些技术。
我们保证 Firefox 会越来越快,再也不会变慢
除了我们必须要做的这些重大的架构改变之外,一些性能缺陷也在我们没有注意的情况下进入了代码库。
所以我们新建了量子的另外一部分去修复它,它会发现这些问题,然后 Mozilla 团队会解决这些问题。
Quantum Flow
Quantum Flow 的团队是强大的,但他们不关注具体子项目的进度,他们主要关注的是一些特殊的场景,例如,社交媒体的信息流的加载,和研究如何让 Firefox 加载得更快。
Quantum Flow 给我们带来了巨大的性能优势。在此过程中,我们还开发了工具和具体流程为了更容易的找到了追踪类似的问题。
Quantum Flow 现在怎么样了?
在这个过程中们非常成功 —— 一次识别并集中在一个关键案例上 —— 并把它变成我们的工作流程的一部分。为了做到这一点,我们将要提高我们的工具,所以我们不再需要一支专门的团队来解决特定的问题,而是更多的工程师追踪这些问题并解决问题。
但是用这种方法有一个难题。当我们优化一个用例时,我们需要逆优化另一个。为了防止这种现象,我们添加了许多新的跟踪,包括改进 CI 自动化运行性能测试,遥测跟踪用户体验,以及 bug 内部的回归管理。通过这些举动,我们期望 Firefox Quantum 会越来越好。
明天只是个开始
明天对于在 Mozilla 的我们来说是一个重要的日子。在过去一年里我们一直致力于让 Firefox 变得更快,但这也仅仅只是一个开始。
在接下来的时间,我们会继续发布新的改进,并且和大家分享这些改进。
访问 Try Firefox Quantum in Release 或者 Developer Edition 以确保大家可以获取最新的更新。
关于作者
Lin Clark 是 Mozilla Developer Relations 团队的一员,她使用 JavaScript、WebAssembly、Rust 和 Servo,并且会画关于编程的漫画。