人们或许已经意识到,Firefox 浏览器又变快了。
过去的七个月中,Firefox 的开发团队非常迅速地替换了浏览器引擎的主要部件,将 Rust 开发语言和 Servo 引擎的一部分引入 Firefox。另外,他们组织了一支攻坚浏览器性能的团队,通过筛查代码库来寻找任何明显的或者不明显的性能问题。
他们将这个项目称为 Quantum。重生后的 Firefox Quantum 的第一个通用版本在 11 月 14 日发布。但这并不意味他们努力的终止,也不意味着如今的 Firefox 的运行速度和响应速度已经足够快了。
因此,让我们来看一看火狐是如何恢复快速的,它又将如何变得更快。
为了变得更快,他们需要利用过去 10 年硬件变化的方式。
Firefox 并不是第一个这样做的团队。最开始 Chrome 团队这样做之后,Chrome 的运行速度和响应速度就变得比 Firefox 更快了。Chrome 变快的其中一个原因就是,Chrome 工程师发现了硬件发生的变化并开始更好地利用新的硬件。
新型的 CPU 越来越流行。这些新型 CPU 拥有多个核心,这意味着这些核心能以并行的方式在同一时间各自独立完成任务。
这其实非常复杂。并行模式下,会引入难以发现和调试的复杂 bug。例如,如果 2 个 CPU 核心都需要在内存中对同一个数值做加 1 操作,那么你不特别小心的话,其中一个核心的操作很可能会覆盖另外一个核心的操作。
一个非常简单的避免这种 bug 的方法是,确保你正在操作的两个事物不需要共享内存,也就是说,将你的程序划分成不需要相互协作的大型任务。这就是所谓的粗粒度并行。
在浏览器中,这些粗粒度任务非常容易区分。每个 tab 页作为一个粗粒度任务独立工作。也有一些浏览器,例如 Chrome 浏览器,围绕 web 页面进行优化,每个页面可以独立处理。
这样,每个页面可以并行运行,以各自的速度工作,不会相互阻塞。如果在一个后台 tab 页中有一个非常耗时的运行脚本,它不会阻塞当前 tab 页面的工作。
这就是 Chrome 工程师提前发现的机遇。Firefox 团队其实也看到了这个机遇,但是他们经历了一段崎岖的过程才实现它。由于他们拥有历史遗留的代码库,因此他们需要规划如何拆分遗留的代码库来利用多核硬件。
虽然耗费了一些时间,但是他们也最终实现了目标。通过 Electrolysis 项目,他们最终让多核处理成为 Firefox 的默认功能,所有用户都从中受益。Quantum 还通过其它一些项目让他们将粗粒度并行应用得更好。
Electrolysis 项目为 Quantum 项目奠定了基础。Electrolysis 项目引入了一种类似 Chrome 使用的多线程架构。由于这是一个非常大的改动,因此他们从 2016 年开始非常谨慎地引入这种架构,慢慢地用一小部分用户来测试这种变动,直到 2017 年中旬才将它开放给所有 Firefox 用户。
Quantum Compositor 将排字器转移到一个独立的进程中。这样做最大的一个好处是,它让 Firefox 更加稳定。拥有一个独立进程,意味着如果图形驱动崩溃,Firefox 不会整体崩溃。另外,拥有这样的独立进程,也可以提升 Firefox 的响应速度。
即使你将内容窗口拆分到多个 CPU 核心,并为每一个内容窗口提供一个独立的主线程,每个主线程仍然有许多任务需要完成。并且其中一些任务比其它任务更重要。例如,响应一个 keypress 事件比运行垃圾回收更重要。Quantum DOM 给他们提供了一种方法对这些任务排优先级。这大大提升了 Firefox 的响应速度。这些工作大部分已经完成,但是 Firefox 团队还计划深入研究 "抢先调度(pre-emptive scheduling)" 来进一步改进。
然而,展望未来时,Firefox 团队需要研究比粗粒度并行更优秀的架构。
虽然粗粒度并行很好地利用了硬件资源,但是这种利用并不充分。当你将 web 页面分隔到不同的 CPU 核心中,其中一些核心并没有工作需要做。那么,这些核心就会闲置。并且,在一个新 CPU 核心中打开一个新页面和在单核 CPU 中打开一个新页面花费的时间几乎相同。
如果能够在加载新页面时利用所有这些 CPU 核心来进行处理,就可以更快地完成页面加载。这会非常棒。
但是在粗粒度并行架构下,很难将这些工作从一个核心分配给其它的核心。因为这些工作间没有边界。
在细粒度并行架构下,可以将大的任务拆分到更小的单元中,而这些单元可以被分配给不同的核心。例如,类似 Pinterest 的网站,可以将不同的固定项目拆分,然后分配到不同的核心进行处理。
这不仅减少了粗粒度并行架构的延迟,还在纯速度方面有所提升。因为加载工作被分配到所有的核心,因此页面可以加载得更快。而且你增加的核心越多,你的页面加载速度就会越快。
Firefox 团队已经看到了这是未来趋势,但是还不清楚如何能够实现这一点。因为要想使这种细粒度并行架构快速运行,需要在多个核心间共享内存。这就会造成 Lin Clark 以前提到的 data race 问题 (data race 是指,在一个线程中存在 2 个已上的线程并发访问共享内存,至少其中之一是写操作,这些线程还不使用排它锁来控制对内存的访问,这会造成数据结果的不确定性的情况。虽然有些 data race 是无害的,但大部分 data race 会造成程序 bug)。
但是 Firefox 的开发团队知道,浏览器必须做出这样的转变,因此开始投入研究。他们发明了一种语言——Rust,它可以非常容易解决这些 data race 问题。他们还发明了一个浏览器引擎——Servo,它可以完全利用这种细粒度架构。通过这些,他们证明了细粒度并行架构确实可行,浏览器可以在更快运行的同时拥有更少的 bug。
通过 Stylo ,CSS 样式计算工作完全并行运行在所有 CPU 核心中。Stylo 运用了一项叫做工作窃取(work stealing)的技术来将工作有效率地分配给各个核心,让所有 CPU 核心都保持忙碌。这样,样式计算工作得到线性加速。你将进行 CSS 样式计算所需要的时间分摊给所有你使用的 CPU 核心。
另外一种高度并行的硬件是 GPU。它拥有成百上千个核心。因此,你必须做许多规划来确保这些核心尽可能忙碌。 这些就是 WebRender 做的事情 。
WebRender 将在 2018 年发布,他会利用现代 GPU。同时,我们也会从另外一个角度攻克这个难题。Advanced Layers 项目修改了 Firefox 现存的分层系统来支持批渲染。它通过优化 Firefox 目前的 GPU 使用方式,给了我们立竿见影的效果。
Firefox 团队认为渲染流程的其他部分也会从这种细粒度并行架构中受益。在接下来的数月里,他们将密切关注还有哪些方面可以使用这些技术。
除了这些他们已经知道将不得不进行的主体架构上的变动,还有许多他们因为疏忽而引入代码库的性能 bug 需要修复。
因此,我们创造了 Quantum 的另外一部分来修复这些问题...... 基本上是通过一支浏览器攻性能坚团队来发现这些问题并组织团队修复它们。
Quantum Flow 团队就是这种攻坚力量。与集中于一个特定子系统的整体性能不同,他们首要集中于一些特定的重要的用例,例如,加载社交媒体种子,跨团队来搞清楚为什么 Firefox 比其它浏览器响应慢。
Quantum Flow 带来巨大的性能优势。同时,他们还开发了许多工具和流程来更容易地发现和跟踪这类型的问题。
那么 Quantum Flow 目前怎么样了?
Quantum Flow 是如此高效识别问题并且每次聚焦一个关键用例,他们将它作为常规工作流程的一部分。为了实现这点,他们正升级工具,这样就不需要一支专门的攻坚力量来寻找问题,而是让组织内更多的工程师有能力发现这些问题。
但是这个方案也有一个问题。当优化了一个用例时,可能会让另外一个用例退化。为了防止这种情况,他们增加了许多新的监测手段,包括优化持续集成自动化来运行性能测试、跟踪观测用户体验以及 bug 回归管理。通过这些,他们期望 Firefox Quantum 持续变得更好。
11 月 14 日对于 Firefox 团队来说,是在 Mozilla 重要的一天。他们在过去的一年中非常努力来让 Firefox 更快。但这仅仅只是开始。
他们将在接下来的一年持续交付性能方面的优化,期待将这些分享给你!
当 Firefox Quantum 正式版本 或 开发者版本 发布时,可以尝试它们,来确保你能够获取到最新的更新。
来源: http://www.infoq.com/cn/articles/how-firefox-got-fast-again-and-where-its-going-to-get-faster