在谷歌浏览器随便打开一个页面,点击“选项”菜单,选择“更多工具”,点击“任务管理器”,这将打开Chrome的任务管理器的窗口,你会发现一个页面上有四个以上的进程。为何会有四个进程呢? 本章经过分析浏览器的进化史而展开探讨这个问题。
开始以前,咱们必须得了解一下这个进程
与线程
的概念。html
线程这个东西它是不能单独存在的,它是由进程来启动和管理的。
web
一个进程就是一个程序的运行实例
。算法
线程是依附于进程的,而进程中使用多线程并行处理能提高运算效率
。浏览器总结,线程与进程之间的关系有如下四个特色:缓存
- 进程中任一线程执行出错,都会致使整个进程崩溃。
- 线程之间共享进程的数据。
- 当一个进程关闭以后,操做系统会回收进程所占用的内存。
- 进程之间的内容都互相隔离。(若是进程之间须要进行数据的通讯,这时候须要使用用于进程间通信(IPC)机制了)。
早在07年以前,市面上的浏览器都是单进程的。单进程,顾名思义是指:浏览器的全部功能模块都运行在同一个进程里。
如此多的功能模块运行在一个进程里,致使单进程浏览器不稳定
、不流畅
、不安全
。
具体的表现就不说了,总之体验很是差,因而进入了“多线程浏览器”时代。安全
- 多进程浏览器因为进程相互隔离,因此当一个页面或者插件崩溃的时候,影响的仅仅是当前的页面进程或者插件过程。这就完美解决了页面或者插件崩溃而致使的整个浏览器崩溃问题。JS的渲染若出现问题,影响的一样是当前的渲染页面,没有响应的仅对当前页面。并且在多进程浏览器时代,当关闭一个页面的时候,整个渲染进程会被关闭,该进程占用的内存都会被系统回收,这样也就轻松解决了浏览器页面的内存泄露问题。
- 此外有关安全方面的问题:使用多线程架构可使用
安全沙箱
。能够把沙箱当作是操做系统给进程上了一把锁,沙箱里面的程序能够运行,可是不能在硬盘上写入任何数据,也不能在敏感位置读取任何数据(例如文档和桌面),Chrome把插件进程和渲染进程锁在沙箱里面,这样即便在渲染进程或者插件进程里面执行了恶意程序,恶意程序也没法突破沙箱去获取系统权限。服务器
最新的Chrome进程架构:Chrome浏览器包括:
1个浏览器(Brower)主进程,1个GPU进程、一个网络(NetWork)进程、多个渲染进程和多个插件进程
。
虽然多进程模型提高了浏览器的稳定性、流畅性、安全性,可是一样也会不可避免带来一些问题:微信
更高的资源占用
:由于每一个进程都会包含公共基础结构的副本(如JavaScript运行环境),这意味着浏览器会消耗更多的资源。更复杂的体系架构
:浏览器各模块之间耦合性高、扩展性差等问题,会致使如今的架构已经很难适应新的需求。
为了解决这些问题,2016年,Chrome团队使用“面向服务的架构“(SOP)思想设计了新的Chrome架构,这也是现阶段Chrome团队的一个主要任务。网络
在衡量Web页面性能的时候有一个重要的指标叫"FP(First Paint)",是指从页面加载到首次开始绘制的时长。其中影响FP的一个重要因素就是
网络加载速度
。数据结构要优化网络加载速度,须要对网络有充分的了解,这一节重点介绍
在Web世界中的TCP/IP是如何工做的
。在网络中,一个文件一般会被拆分为不少数据包来进行传输,而数据包在传输过程当中有很大概览丢失或者出错,那么如何保证页面文件能被完整地送达浏览器?
IP:把数据包送达目的主机
计算机的地址称为IP地址,访问任何网站实际上只是你的计算机向另一台计算机请求信息。
当从主机A向主机B发送数据(即发送数据包),传输前,数据包会被附加上主机A和主机B的IP地址信息,这些信息会被封到一个叫作IP头的数据结构里,在这个IP头中包含IP数据包开头的信息(IP版本、源IP地址、目标地址、生存时间等信息),因而数据包从主机A发送到主机B。UDP:把数据包送达应用程序 IP经过IP地址信息把数据包发送给指定的电脑,而UDP经过端口号把数据包发给正确的程序。 UDP发送数据,有各类因素会致使数据包出错,虽然UDP能够校验数据是否正确,可是
UDP不提供重发机制
,只是丢弃当前的包,且UDP在发送以后没法知道可否到达目的地。
UDP不能保证数据可靠性,可是传输速度却很是快
,所以UDP应用在一些关注速度但不那么严格要求数据完整性的领域,例如:在线视频、互动游戏等。TCP:把数据完整的送达应用程序 TCP(Transmission Control Protocol,传输控制协议):他是一种面向链接的、可靠的、基于字节流的传输层通讯协议。相对于UDP而言:
- 对于数据包丢失状况,提供重传机制。
- TCP引入数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。
咱们如今已经知道TCP单个数据包的传输流程和UDP流程差很少,不一样在于,经过TCP头信息能够保证一块大的数据传输的完整性。 一个完整的TCP链接过程,其生命周期包括了“创建链接“、”数据传输“、”断开链接“三个阶段。
- 创建链接阶段:这个阶段经过“三次握手”来创建客户端和服务器之间的链接。
- 数据传输阶段:在该阶段,接收端须要对每一个数据包进行确认操做。接收端应该在接收数据后要发送确认数据包给发送端,若发送端没有接收到这个确认,则判断数据包丢失,并触发发送端的重发机制。
- 断开链接阶段:数据传输完毕,终止链接,经过最后一个阶段“四次挥手”来保证双方都能断开链接。
首先的首先咱们知道:HTTP协议创建在TCP链接基础之上的。
HTTP是一种容许浏览器向服务器获取资源的协议,是Web的基础。HTTP是浏览器使用最广的协议
。简单说说HTTP和TCP的关系:浏览器使用HTTP协议做为
应用层协议
,用来封装请求的文本信息,并使用TCP/IP做为传输层协议
将它发到网路上,因此HTTP工做前,须要经过TCP与服务器创建链接,也就是说:HTTP的内容是经过TCP的传输数据阶段来实现的
。
若是在浏览器地址栏里输入:www.liugezhou.online 这个网址后,浏览器这个庞然大物,它的背后都作些什么呢?
首先浏览器构建请求行信息,构建好以后,浏览器准备发起网路请求。
在准备发起网路请求阶段,浏览器偷偷的在它的缓存中查询是否有要请求的资源。
如有:拦截请求,返回资源副本,直接结束请求。
若缓存查找失败:继续下一步。
这个IP地址和端口号的获取,确定是经过域名与其映射,即“域名系统”,也就是咱们熟知的DNS。 因而,浏览器第一步会请求DNS返回域名对应的IP,若是没有特别指明端口号,则默认为80。 (浏览器提供了DNS数据缓存服务,若缓存过也就不会去请求,直接解析。从而减小一次网络请求)
拿到IP地址与端口号后,还须要在TCP队列中排队才能创建TCP链接。
这是由于:Chrome有个机制,同一个域名同时最多只能创建6个TCP链接,若此刻同时有10个请求发生。则四个会进入TCP队列进行排队。 固然,若当前请求数量少于6个,则会直接进入下一步。
创建TCP链接,上一节咱们已经知道,一个完整的TCP链接过程包括“创建链接”、“数据传输”、“断开链接“三个阶段。
HTTP请求是在TCP链接的数据传输阶段工做的,这个时候浏览器向服务器发送请求行,它包括请求方法、请求URI、HTTP版本协议。,HTTP中的数据在这个通讯过程当中传输。
这里能够在命令行中输入
curl -i https://www.google.com
来查看返回请求数据。 (-i 返回响应行、响应头和响应体信息。 -I 不返回响应体。)
返回网站的HTTP协议、Connection、Location、Cache-Control等信息。一般状况,一旦服务器向客户端返回了请求数据,它就要关闭TCP链接,可是若是浏览器或者服务器设置了
Connection:keep-alive
,那么TCP链接在发送后将仍保持打开状态。保持TCP链接能够省去下次请求时须要创建链接的时间,提高资源加载速度
。
主要缘由确定是第一次加载页面的过程当中,缓存了一些数据(从上面的过程分析,咱们知道
DNS缓存
和页面资源缓存
这两块数据是会被浏览器缓存起来的).
网站把不少资源都缓存到了本地,浏览器缓存直接使用本地副原本回应请求,而不会产生真实的网络请求,从而节省了时间。
简单地说,若是服务器端发送的响应头内有 Set-Cookie 的字段,那么浏览器就会将该字段的内容保持到本地。当下次客户端再往该服务器发送请求时,客户端会自动在请求头中加入 Cookie 值后再发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查到底是从哪个客户端发来的链接请求,而后对比服务器上的记录,最后获得该用户的状态信息。
流程开始前,回顾下浏览器进程、网络进程、渲染进程的各自主要职责:
- 浏览器进程:主要负责
用户交互
、子进程管理
和文件储存
等功能。- 网络进程:面向渲染进程或浏览器进程提供
网络资源下载
。- 渲染进程:将HTML、CSS、JS、图片等资源解析为能够显示和交互的页面。
- 首先,用户从浏览器进程中输入请求信息。
- 而后,网络进程发起URL请求。
- 服务器响应URL请求后,浏览器进程开始准备渲染进程。
- 渲染进程准备好之后,须要先向渲染进程提交页面数据,这称之为文档提交阶段。
- 渲染进程接收到文档信息以后,便开始解析页面和加载子资源,完成页面的渲染。 这其中,用户发出URL请求到页面开始解析的过程,就叫作导航。
- 响应数据类型处理:根据服务端返回的
Content-Type
字段来决定如何显示响应体的内容。- 同一站点下的多个页面会运行在一个渲染进程中。
- 用户输入url并回车·
- 浏览器进程检查url,组装协议,构成完整的url
- 浏览器进程经过进程间通讯(IPC)把url请求发送给网络进程
- 网络进程接收到url请求后检查本地缓存是否缓存了该请求资源,若是有则将该资源返回给浏览器进程
- 若是没有,网络进程向web服务器发起http请求(网络请求),请求流程以下: 5.1 进行DNS解析,获取服务器ip地址,端口 5.2 利用ip地址和服务器创建tcp链接 5.3 构建请求头信息 5.4 发送请求头信息 5.5 服务器响应后,网络进程接收响应头和响应信息,并解析响应内容
- 网络进程解析响应流程; 6.1 检查状态码,若是是301/302,则须要重定向,从Location自动中读取地址,从新进行第4步
6.2 200响应处理: 检查响应类型Content-Type,若是是字节流类型,则将该请求提交给下载管理器,该导航流程结束,再也不进行后续的渲染,若是是html则通知浏览器进程准备渲染进程准备进行渲染。- 准备渲染进程 7.1 浏览器进程检查当前url是否和以前打开的渲染进程根域名是否相同,若是相同,则复用原来的进程,若是不一样,则开启新的渲染进程
- 传输数据、更新状态 8.1 渲染进程准备好后,浏览器向渲染进程发起“提交文档”的消息,渲染进程接收到消息和网络进程创建传输数据的“管道” 8.2 渲染进程接收完数据后,向浏览器发送“确认提交” 8.3 浏览器进程接收到确认消息后更新浏览器界面状态:安全、地址栏url、前进后退的历史状态、更新web页面。
按照渲染的时间顺序,渲染流水线可分为如下几个构建阶段:
构建DOM树
、样式计算
、布局阶段
、分层
、绘制
、光栅化
、合成
。 本节主要讨论前三个阶段。
由于浏览器没法直接理解和使用 HTML,因此须要将 HTML 转换为浏览器可以理解的结构——DOM 树。 DOM树和HTML内容几乎同样,但和HTML不一样的是:DOM是保存在内存中的树结构。
- 把CSS转换为浏览器可以理解的结构。
- 转换样式表中的属性值,使其标准化。
「例如rem -> px, red -> rgb(255,0,0),bold -> 700」- 计算出DOM树中每一个节点的具体样式。
「CSS继承:每一个DOM节点都包含有父节点的样式」
「CSS层叠:它在 CSS 处于核心地位,定义了如何合并来自多个源的属性值的算法」
「样式来源:若是一个元素不提供任何样式,默认使用的是UserAgent样式---浏览器提供的一组默认样式」。
内容: 布局阶段是根据DOM树和样式计算出元素的几何位置。
- 建立布局树「构建一颗只包含可见元素的布局树」
- 布局计算
「在执行布局操做的时候,会把布局运算的结果从新写回布局树中,因此布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,由于在布局阶段并无清晰地将输入内容和输出内容区分开来。针对这个问题,Chrome 团队正在重构布局代码,下一代布局系统叫
LayoutNG
,试图更清晰地分离输入和输出,从而让新设计的布局算法更加简单。」
为了生成一些复杂效果(3D变换、页面滚动、z轴排序等),渲染引擎还须要为特定的节点生成专用的图层,生成一颗对应的图层树.
- 并非布局树的每一个节点都包含一个图层,若是一个节点没有对应的层,那么这个节点就从属于父节点的图层.
- 素有了层叠上下文的属性或者须要被剪裁,知足这任意一点,就会被提高成为单独一层。
一个图层的绘制拆分红不少小的绘制指令,而后再把这些指令按照顺序组成一个
待绘制列表
。「可在浏览器开发者工具的Layers中查看。」
所谓栅格化,是指将图块转换为位图。
栅格化过程都会使用 GPU 来加速生成,使用 GPU 生成位图的过程叫快速栅格化,或者 GPU 栅格化,生成的位图被保存在 GPU 内存中.
一旦全部图块都被光栅化,合成线程就会生成一个绘制图块的命令——“DrawQuad”,而后将该命令提交给浏览器进程。通过浏览器就会显示出页面。
一个完整的渲染流程大体可总结为以下:
- 渲染进程将 HTML 内容转换为可以读懂的 DOM 树结构。
- 渲染引擎将 CSS 样式表转化为浏览器能够理解的 styleSheets,计算出 DOM 节点的样式。
- 建立布局树,并计算元素的布局信息。对布局树进行分层,并生成分层树。
- 为每一个图层生成绘制列表,并将其提交到合成线程。
- 合成线程将图层分红图块,并在光栅化线程池中将图块转换成位图。
- 合成线程发送绘制图块命令 DrawQuad 给浏览器进程。浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。
使用CSS或者JS使元素的几何位置发生了改变,例如改变元素的宽度、高度等,这会使得浏览器触发从新布局、解析以后的一系列子阶段,这个过程就是重排。无疑,重排须要更新完整的渲染流水线,因此开销是最大的。
好比改变了元素的背景色,这会触发浏览器进行重绘以后的操做。相较于重排操做,重绘省去了布局和分层阶段,因此执行效率会比重排操做要高一些。
那若是你更改一个既不要布局也不要绘制的属性,会发生什么变化呢?渲染引擎将跳过布局和绘制,只执行后续的合成操做,咱们把这个过程叫作合成. 例如CSS的transform实现的动画效果,能够避开重排和重绘阶段,相对于重绘和重排,合成能大大提高绘制效率。
若有疑问请添加个人微信号:18231133236。欢迎交流!
更多内容,请访问的个人我的博客:www.liugezhou.online.
您也能够关注个人我的公众号:【Dangerous Wakaka】