现代浏览器探秘(part 1):架构

1,750 阅读9分钟

链接:developers.google.com/web/updates…

翻译:疯狂的技术宅

CPU,GPU,内存和多进程架构

在这个由4部分组成的系列文章中,我们将介绍Chrome浏览器从高级架构到渲染管道的具体细节。 如果你想知道浏览器是如何将你的代码转换为功能性网站的,或者你想知道为什么需要使用某些特定技术来提高性能,那么本系列非常适合你。

作为本系列的第1部分,我们将介绍核心计算术语和Chrome的多进程架构。

注意:如果你熟悉CPU / GPU和进程/线程的概念,则可以跳到本文的浏览器体系结构部分。

计算机的核心是CPU和GPU

为了理解浏览器运行的环境,我们需要了解一些计算机部件及其功能。

CPU

首先是中央处理单元(Central Processing Unit)—— CPU。 CPU可以被认为是你计算机的大脑。 CPU核心,在这里作为办公室工作人员,可以在他们进来时逐个处理许多不同的任务。它可以处理从数学到艺术的所有事情,同时知道如何回复客户呼叫。 在过去,大多数CPU都是单芯片。 核心就像生活在同一芯片中的另一个CPU。 在现代硬件中,你通常会获得多个核心,从而为你的手机和笔记本电脑提供更强的计算能力。

图1:4个CPU核心作为办公室工作人员坐在每个办公桌处理任务

GPU

图形处理单元(Graphics Processing Unit )—— GPU是计算机的另一部分。 与CPU不同,GPU擅长处理简单任务,但同时跨多个核心。 顾名思义,它最初是为处理图形而开发的。 这就是为什么在图形环境中“使用GPU”或“GPU支持”与快速渲染和平滑交互相关联。 近年来,随着GPU加速计算,仅在GPU上就可以实现越来越多的计算。

图2:许多带有扳手的GPU核心表明它们可以处理有限的任务

当你在计算机或手机上启动程序时,CPU和GPU用来支持程序的运转。 通常,程序使用操作系统提供的相关机制在CPU和GPU上运行。

图3:三层计算机体系结构。 机器硬件位于底部,操作系统位于中间,应用程序位于顶部。

在进程和线程上执行程序

在深入浏览器架构之前要掌握的另一个概念是Process和Thread。 进程可以描述为运行状态中的程序。 线程是存在于进程内部并用来执行其程序任务的某一部分。

图4:过程划定了边界,线程作为在进程内游动的“抽象鱼”

启动程序时,将会创建一个进程。 该程序可能会创建线程来帮助它工作,但这是可选的。 操作系统为进程提供了一“块”内存,并且所有程序状态都保存在该专用内存空间中。 当你关闭程序时,该进程也会消失,操作系统会释放内存。

图5:进程使用内存空间和存储数据的示意图

进程可以要求操作系统启动另一个进程来执行不同的任务。 当这种情况发生时,将为新进程分配不同的内存。 如果两个进程需要通信,他们可以通过使用进程间通信(IPC)来实现。 许多程序都是以这种方式工作的,因此如果一个工作进程失去响应,则可以重新启动它,而不会停止运行程序的其他进程。

图6:通过IPC进行通信的独立进程示意图

浏览器架构

那么如何使用进程和线程构建Web浏览器? 好吧,它可能是一个具有许多不同线程的进程,或是许多具有少量线程的通过IPC进行通信的不同进程。

图7:不同浏览器体系结构中的进程/线程示意图

在这里有非常重要的一点需要注意,这些不同的架构是实现细节。关于如何构建Web浏览器并没有标准规范。 一种浏览器可能与另一种浏览器的结构完全不同。

在本系列文章中,我们将使用下图中描述的Chrome最新架构。

最重要的部分是浏览器进程怎样与程序的其他工作进程进行协调。 对于渲染器进程,将创建多个进程并将其分配给每个选项卡。 直到不久前,Chrome才为每个标签提供了一个进程;现在它尝试为每个站点提供自己的进程,其中包括iframe(请参阅:站点隔离部分)。

browser architecture

图8:Chrome的多进程架构图。 渲染进程下显示多个图层,表示Chrome为每个选项卡运行多个渲染器进程。

每个进程都做些什么?

下表介绍了每个Chrome进程及其控制的内容:

进程 做些什么
Browser 控制程序的“chrome”部分,包括地址栏,书签,后退和前进按钮。
还处理Web浏览器的不可见的,和特权部分,例如网络请求和文件访问。
Renderer 负责显示网站的选项卡内的所有内容。
Plugin 控制网站使用的所有插件,例如flash。
GPU 独立于其他进程的GPU处理任务。 它被分成多个不同的进程,因为GPU处理来自多个程序的请求并将它们绘制在同一个面中。

图9:指向浏览器UI不同部分的不同进程

还有更多的进程,如扩展进程和功能进程。 如果你想查看Chrome中正在运行的进程数,请点击右上角的选项菜单图标“more_vert”,选择“更多工具”,然后选择“任务管理器”。 这将打开一个窗口,其中包含当前正在运行的进程列表以及它们使用的CPU/内存量。

Chrome中多进程架构的好处

前面我曾提到Chrome使用多个渲染器进程。 在最简单的情况下,你可以想象每个选项卡都有自己的渲染器进程。 假设你打开了3个选项卡,每个选项卡都由独立的渲染器进程运行。 如果一个选项卡没有响应,就可以关闭无响应的选项卡并继续运行,同时保持其他选项卡处于活动状态。 如果所有选项卡都在一个进程上运行,那么当一个选项卡无响应时,所有选项卡都不会响应。 那将会很难受。

图10:显示多进程运行每个选项卡的示意图

将浏览器的工作分成多个进程的另一个好处是安全性和沙盒。由于操作系统提供了限制进程权限的方法,因此浏览器可以从某些功能中对某些进程进行沙箱处理。 例如,Chrome浏览器限制任意用户输入进程的(如渲染器进程)的任意文件访问。

由于进程有自己的私有内存空间,因此它们通常包含公共基础结构的副本(例如V8是Chrome的JavaScript引擎)。 这意味着会消耗更多的内存空间,因为如果它们运行在同一进程内的不同线程上,则无法遵循自己的机制进行共享。 为了节省内存,Chrome限制了它可以启动的进程数量,这种限制因设备的内存和CPU功率而异,但当Chrome达到限制时,它会在一个进程中运行从同个一站点打开的多个选项卡。

节省更多内存:Chrome中的服务化

同样的方法适用于浏览器进程。 Chrome正在进行体系结构的变更,以便将浏览器程序的每个部分作为一项服务运行,从而可以轻松拆分为不同的流程或汇总为一个流程。

一般的想法是,当Chrome在强大的硬件上运行时,它可能会将每个服务拆分为不同的进程,从而提供更高的稳定性,但如果它位于资源有限的设备上,则Chrome会将服务整合到一个进程中,从而节省内存占用。 在进行这种更改之前,在Android平台上已经使用了类似的方法来整合进程以减少内存使用。

图11:Chrome的服务化示意图,将不同的服务转移到多个进程或一个浏览器进程中

帧渲染器进程:站点隔离

网站隔离是Chrome中最近推出的一项功能,可为每个跨网站的iframe运行单独的渲染进程。 我们一直在讨论每个选项卡一个渲染进程的模型,它允许跨站iframe在单个渲染器进程中运行,并在不同站点之间共享内存空间。 在同一个渲染进程中运行a.com和b.com似乎没问题。 同源策略是Web的核心安全模型,它确保一个站点在未经同意的情况下无法访问其他站点的数据。 绕过此策略是安全攻击的主要目标。进程隔离是分离站点的最有效方法。 由于Meltdown和Spectre漏洞,我们更加需要使用进程来隔离站点。 默认情况下,自从Chrome 67启用桌面隔离功能后,选项卡中的每个跨站点iframe都会得到单独的渲染进程。

图12:站点隔离示意,指向站点内iframe的多个渲染器进程

启用站点隔离是一项需要很多年的工作。 站点隔离并不像分配不同的渲染进程那么简单;它从根本上改变了iframe彼此的交流方式。 在运行着不同iframe进程的的页面上打开devtools,意味着devtools必须在背后做大量的工作才能使其看起来无缝。即使通过简单的 Ctrl + F 来查找页面中的单词也意味着需要跨越不同的渲染进程进行搜索。 这就是浏览器工程师将站点隔离的发布作为一个重要里程碑的原因!

总结

在这篇文章中,我们介绍了浏览器体系结构的高级视图,并介绍了多进程体系结构的优点。 我们还介绍了Chrome中与多进程架构密切相关的服务化和站点隔离。 在下一篇文章中,我们将开始深入研究在显示一个网站时,这些进程和线程之间究竟发生了什么事情。