CPU、GPU、内存以及多进程架构
console.info
本文翻译自 Google 的官方文档。该系列共 4 篇文章,主题为从内部观察现代浏览器(Chrome),主要介绍浏览器的内部架构,以及浏览器从输入 URL 到页面呈现的全过程。
前言
作为本系列的第一篇,我们先来了解一下计算机的核心术语和 Chrome 的多进程架构模型。
计算机的核心——CPU & GPU
在了解浏览器是如何运行之前,我们必须对它所处的运行环境有所了解,毕竟浏览器是基于这些硬件的。
CPU 中央处理器

CPU(Central Processing Unit) 是计算机的大脑。一个 CPU 核心就像一名员工,能够逐个处理分配给它的任务。它可以接收包括数学、艺术在内的各种任务,并将处理结果返回给任务的发布者。
过去,大多数 CPU 都是单核的;而目前,我们经常使用多核 CPU,为计算机提供更加强大的计算能力。
GPU 图像处理单元

GPU(Graphics Processing Unit) 是计算机的另一个重要组成部分。与 CPU 不同,GPU 更擅长处理简单任务,同时一个任务可以由多个 GPU 核心共同处理。
GPU 顾名思义,它的出现就是为了处理图像任务。我们常说的“使用 GPU”“GPU 支持”,就是使用 GPU 实现快速渲染和平滑交互。近些年,随着 GPU 的迅速发展,越来越多的计算任务可以单独运行在 GPU 上。
计算机的三层架构
当你在计算机或手机上打开一个应用时,CPU 和 GPU 会为应用提供计算能力。但是,应用不能直接调用 CPU 或 GPU,必须通过操作系统提供的相关 API 来处理任务。

进程(Process)& 线程(Thread)
在深入了解浏览器(Chrome)前,我们还需要了解操作系统提供的两个概念:进程(Process)和线程(Thread)。
进程可以被认为是应用的执行程序,而线程则由进程创建,执行进程所分配的部分任务。

当你打开一个应用程序时,一个进程就会被创建,该进程还可能创建多个线程来帮助它执行程序。
当一个进程被操作系统创建时,操作系统同时会为该进程分配一定大小的内存空间,用来存储进程在执行过程中产生的数据。
不同的进程享有不同区域的内存空间,当进程退出时,进程所占用的内存空间也会得到释放。
一个进程可以向操作系统请求启动另一个进程来帮助它执行任务。由于不同进程占用不同的内存空间,所以各个进程所存储的数据并不共享。如果进程间需要进行数据交互,就只能通过 IPC(Inter Process Communication) 的方式。
许多应用程序被设计成多进程,一个重要原因就是:当某个进程无响应时,只需重新启动该进程,而其他进程不会受到影响。
浏览器架构
了解进程和线程后,浏览器是如何使用它们来构建架构的呢?总的来说有两种方式:
- 使用一个进程及其创建的多个线程,处理网络请求、页面渲染等任务。
- 创建多个进程来处理不同任务,并通过
IPC进行进程间通信。

不同的浏览器架构有着不同的实现细节,如何实现一个浏览器也没有固定的标准。因此在这个系列中,我们所描述的浏览器架构是针对 Chrome 浏览器的。
Chrome 采用多进程架构。处在顶端的是浏览器进程(主进程),负责渲染基础部分的 UI,以及协调其他进程处理浏览器中的不同任务。主进程会根据选项卡的情况创建多个渲染进程。Chrome 会为每个选项卡创建一个渲染进程来处理渲染任务,也会尝试为每个站点创建单独的进程,包括 iframe。

不同进程处理的任务
下表展示了进程名称及其承担的任务:
| 进程名 | 任务 |
|---|---|
Browser(主进程) |
Chrome 最基础的进程,控制标签栏、地址栏、书签、前进后退按钮,以及网络请求和文件访问等基础功能 |
Renderer(渲染进程) |
控制每一个选项卡的窗口部分 |
Plugin(插件进程) |
控制网站使用的插件,比如 Flash |
GPU(GPU 进程) |
处理由其他进程发出的 GPU 任务;它被分成不同的进程,渲染浏览器窗口中的不同部分 |

上面是浏览器中的主要进程。浏览器还会创建其他进程,比如 Extension(扩展进程)和 Utility(公共进程)等。如果你想查看到底有多少进程正在运行,可以依次点击浏览器右上角的 More Tools(更多工具)和 Task Manager(任务管理器)。弹出的窗口会详细列出每个进程的 ID、名称,以及占用的内存和 CPU 资源。
多进程架构的优点
之前,我们提到过 Chrome 会为每个选项卡开启一个进程,那么这样做的优点是什么呢?
试想一个简单的场景,你在 Chrome 上打开了 3 个页面,当一个页面崩溃了会发生什么?
假设浏览器中的 3 个页面共用一个渲染进程,那么其中一个页面崩溃,就会导致这个渲染进程崩溃,其他两个页面自然也会挂掉。如果这 3 个页面分别由 3 个渲染进程渲染,那么单个页面崩溃并不会影响另外两个页面。
浏览器多进程架构的另一个好处在于安全和隐私。由于操作系统可以限制进程的权限,浏览器主进程就能创建只拥有特定权限的进程,使其在沙箱中运行。比如,浏览器创建的渲染进程,其文件访问权限就会受到一定限制。
由于每个进程的内存空间都是私有的,而每个进程都会包含一些公共的基础功能(比如 V8,即浏览器的 JavaScript 解释器),所以进程越多,内存消耗越大。如果不采用多进程架构,而使用“进程—线程”的方式,就能减少内存消耗(线程共享进程占用的内存空间)。因此,Chrome 会根据内存和 CPU 的情况预先确定进程数量的限制。一旦达到限制,Chrome 就会使用“进程—线程”的模式来处理新窗口的创建。
节约内存——Chrome 服务化
同样的节约内存策略也适用于整个浏览器的进程架构。Chrome 在后台运行时,会将不同任务分配给不同进程,或将它们整合进同一个进程。
主要的分配任务的策略如下:
- 当硬件资源充足时,
Chrome将不同任务分配给不同进程,以提高运行的稳定性和效率。 - 当硬件资源有限时,
Chrome会将一些进程的功能汇集到一个进程中,从而节约内存。
单独的渲染进程——站点隔离
站点隔离是 Chrome 最近推出的一项功能,它确保每个跨站点的 iframe 都在单独的进程中渲染。我们之前讨论过,浏览器会给每个选项卡分配一个进程,那么跨站点的 iframe 也会由同一个进程渲染。这样一来,跨站点的 iframe 就会和主站点处于同一个进程中,共用同一片内存区域。
在同一个进程中同时渲染 a.com 和 b.com 的内容似乎没有太大问题,因为同源策略是 Web 的核心安全模型,它确保一个站点不能在未经允许的情况下获取另一个站点的数据。但是,随着 Meltdown 和 Spectre 漏洞的出现,我们必须使用进程隔离来确保站点之间相互隔离。在 Chrome 67 版本之后,站点隔离会自动应用在跨站点的 iframe 上。

站点隔离是多年工程积累的成果,远远不是开启一个渲染进程那么简单。它从根本上改变了该 iframe 与其他页面之间的交互方式。比如,打开 DevTools 时,由于 iframe 位于另一个进程,而进程间又相互独立,DevTools 就必须流畅地完成页面内容的获取与合并。即使是简单的查找功能(Ctrl + F),也要通过搜索多个不同的进程来实现。因此,浏览器工程师将该功能的发布视为一个重要的里程碑。
小结
这篇博文大致介绍了以下内容:
- 浏览器的架构模型。
- 多进程模型的优点。
Chrome的服务化,目的在于节约内存。- 站点隔离的实现方式。
下一篇文章,我们将开始深入研究浏览器为了显示页面,是如何搭配使用这些进程和线程的。