现代网络浏览器概览-1

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

在这个由 4 篇组成的系列博客中,我们将从高级体系架构到渲染流水线的细节来深入了解 Chrome 浏览器。如果你想知道浏览器是如何把你的代码变成一个功能强大的网站的,或者你对为什么用某些特定技术来优化性能的一知半解,那么这个系列博客就是为你准备的。

在第一部分的博客中,我们会来了解核心计算以及 chrome 的多进程架构。

一台电脑的核心是 CPU 以及 GPU

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

CPU

首先是中央处理器--或称 CPU。CPU可以被视为计算机的大脑。一个CPU核心,在图片中被描绘成一个办公室工作人员,可以一个接一个地处理许多不同的任务。它可以处理从数学到艺术的一切事情,同时还知道如何回复客户电话。在过去,大多数CPU都是单核的芯片。一个内核就像另一个住在同一芯片中的CPU。在现代硬件中,你通常拥有多个内核,从而为你的手机和笔记本电脑提供了更多的计算能力。

GPU

图形处理单元-或 GPU 是计算机的另一个部分。与 CPU 不同,GPU 擅长处理简单的任务,但同时跨多个核心。顾名思义,它最初是为了处理图形而开发的。这就是为什么在图形环境中,“使用 GPU”或“由 GPU 支持”与快速渲染和流畅交互联系在一起。近年来,随着 GPU 加速计算,越来越多的复杂计算正在成为可能。 当您在计算机或手机上启动应用程序时,驱动该应用程序的是 CPU 和 GPU。通常,应用程序使用操作系统这个媒介运行在 CPU 和 GPU 上。

在进程和线程上执行程序

首先在深入研究浏览器体系架构之前需要掌握的另一个概念是进程和线程。

进程可以被描述为应用程序的执行程序。一个线程线程是驻留在进程内的,并执行其进程程序的任何部分。

当你启动一个应用程序时,就会相对应的创建一个进程。应用程序可能会创建一些线程来帮助运行,但也不是绝对的。操作系统为进程提供了一块可使用的内存,所有应用程序状态都保存在该私有内存空间中。当您关闭应用程序时,该进程也会消失,操作系统会释放内存

一个进程可以要求操作系统启动另一个进程来运行不同的任务。发生这种情况时,会为新进程分配不同的内存部分。如果两个进程需要通信,它们可以使用进程间通信(IPC)来实现。许多应用程序都是按照这种设计方式来运行的,这样如果某个工作进程没有响应,它可以自己单独得进行重新启动,并且不会影响到其他正在运行的进程。

浏览器架构

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

这里需要注意的是,这些不同的架构是实施细节。对于如何建立一个网络浏览器,并没有标准的规范。一个浏览器的方法可能与另一个完全不同。

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

在图片顶部的是浏览器进程,它负责协调应用程序不同部分的进程进行。对于渲染器进程,我们可以看到创建了多个进程,并分配给每个标签。直到最近,Chrome 在可能的情况下给每个标签一个进程;现在它试图给每个网站提供自己的进程,包括 iframe(详情见网站隔离)。

每种进程都在负责点什么呢?

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

进程及其控制的内容
浏览器主进程(Browser) 控制应用程序 "chrome "的地址栏、书签、后退和前进按钮。
渲染器进程(Renderer) 控制显示网站的标签内的任何内容。
插件进程(Plugin) 控制网站使用的任何插件,例如,Flash。
GPU进程(GPU)

处理与其他进程隔离的GPU任务。它被分离到不同的进程中,因为GPU处理来自多个应用程序的请求,并在同一个表面上绘制它们。

甚至还有更多的进程,如扩展进程和实用工具进程。如果你想看看你的 Chrome 浏览器中有多少进程在运行,点击右上角的选项菜单图标,选择更多工具,然后选择任务管理器。这将打开一个窗口,列出当前正在运行的进程以及它们所使用的 CPU 和内存信息。

Chrome 浏览器中多进程架构的好处

之前,我提到 Chrome 使用了多个渲染器进程。在最简单的情况下,你可以想象每个 Chrome 标签页都有自己的渲染器进程。假设你有 3 个打开的标签页,每个标签页由一个独立的渲染器进程运行。如果一个标签页卡住变得未响应了,那么你可以单独关闭这个没有反应的标签页,并且其他的 2 个标签页不会受到影响。如果所有的标签页都在一个进程上运行,当一个标签页变得没有反应时,所有的标签页都会受到影响。这很糟糕。

浏览器这种多进程的架构还带来了另外的好处安全和沙盒化。因为操作系统提供了一种限制进程权限的方法,所以浏览器可以对某些进程进行沙盒化处理,保证其和某些功能进行隔离。例如,Chrome 浏览器限制处理任意用户输入的进程(如渲染器进程)对任意文件的访问。

由于进程有自己的私有内存空间,它们通常包含通用基础设施的副本(如 V8,这是 Chrome 的 JavaScript 引擎)。这意味着更多的内存使用,因为它们不能像同一进程中的线程那样被共享。为了节省内存,Chrome 对其可以启动的进程数量进行了限制。这个限制取决于你的设备有多少内存和 CPU 能力,但当 Chrome 浏览器达到这个限制时,它就会开始在一个进程中运行同一网站的多个标签。

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

同样的方法也适用于浏览器进程。Chrome 浏览器正在进行架构调整,将浏览器程序的每个部分作为服务运行,允许轻松地拆分成不同的进程或聚合成一个进程。

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

每帧渲染器进程-站点隔离

网站隔离是 Chrome 最近推出的一项功能,它为每个跨网站的 iframe 运行一个单独的渲染器进程。我们一直在谈论每个标签的一个渲染器进程的模式,它允许跨网站 iframe 在一个渲染器进程中运行,并在不同网站之间共享内存空间。在同一个渲染器进程中运行 a.com 和 b.com 可能看起来不错。同源策略是网络的核心安全模式;它确保一个网站未经同意不能访问其他网站的数据。绕过这一政策是安全攻击的一个主要目标。进程隔离是分离网站的最有效方法。随着 Meltdown 和 Spectre 的出现,我们需要用进程来分离网站变得更加刻不容缓。自 Chrome 67 以来,在桌面上默认启用了网站隔离,标签中的每个跨网站 iframe 都有一个单独的渲染器进程。

启用 "站点隔离 "是一项多年的工程努力。网站隔离并不是简单地指定不同的渲染器进程;它从根本上改变了 iframe 之间的对话方式。在一个页面上打开 devtools,并在不同的进程中运行 iframes,意味着 devtools 必须实施幕后工作,使其看起来无缝。即使是运行一个简单的 Ctrl+F 来查找页面中的一个单词,也意味着在不同的渲染器进程中进行搜索。你可以看到为什么浏览器工程师会把网站隔离的发布作为一个重要的里程碑来谈论!

总结

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

你喜欢这个帖子吗?如果你对未来的帖子有任何问题或建议,我很乐意在下面的评论区或 Twitter 上的@kosamari上听到你的意见。

原文链接 inside-browser-part1