浏览器模型问题

多进程与多线程

浏览器的多进程

以chrome为代表的主流浏览器都是使用多进程的模型,主要有五种进程

image-20201021174728754

  • Browser Process: 浏览器主进程,负责主控和调用,创建和销毁其他进程。
  • GPU Process: 主要负责GPU相关操作。
  • Renderer Process: 每创建一个tab页就会开启一个Renderer Process 负责对应的tab页的内部网页呈现的所有,比如说页面渲染,事件执行,脚本执行。这个进程是多线程的。它就是常说的浏览器内核
  • Plugin Process: 启用一个插件就会创建一个对应的进程。

image-20201021175217987

浏览器的多线程

Renderer Process是浏览器为每一个tab页单独启用的进程,所以每一个Renderer Process 都会有独立的渲染引擎实例。一般来说一个tab下会有如下五个线程

image-20201021180735426

  • CUI线程: 这个线程负责渲染页面的html元素,它再重绘和重排的时候会执行。这个线程和 JS引擎线程互斥。

HTML渲染大致分为如下几步:

  1. HTML被HTML解析器解析成DOM Tree, css则被css解析器解析成CSSOM Tree。
  2. DOM Tree和CSSOM Tree解析完成后,被附加到一起,形成渲染树(Render Tree)。
  3. 节点信息计算(重排),这个过程被叫做Layout(Webkit)或者Reflow(Mozilla)。即根据渲染树计算每个节点的几何信息。
  4. 渲染绘制(重绘),这个过程被叫做(Painting 或者 Repaint)。即根据计算好的信息绘制整个页面。

以上4步简述浏览器的一次渲染过程,理论上,每一次的dom更改或者css几何属性更改,都会引起一次浏览器的重排/重绘过程,而如果是css的非几何属性更改,则只会引起重绘过程。所以说重排一定会引起重绘,而重绘不一定会引起重排。

  • JS引擎线程(chrome的V8):JS内核,在后台等待任务,负责解析运行 JS 代码,在一个 Renderer 进程之中同时只能有一个 JS 线程。(JS的单线程性)
  • 定时触发线程:setTimeout和setInterval的计时器线程,由于 JS 的单线程性,所以设计成又单独的线程计时。
  • 事件触发线程:负责将浏览器和其他线程触发的符合要求的事件添加到 JS 引擎队列的末尾,等待 JS 引擎执行。
  • 异步请求线程:在XMLHttpRequest在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript引擎的处理队列中等待处理。

关于JS单线程的解决

为了多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

web workers

web workers的概念

Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。一旦创建, 一个worker 可以将消息发送到创建它的JavaScript代码, 通过将消息发布到该代码指定的事件处理程序(反之亦然)。

web workers的用法

使用构造函数可以创建一个worker对象,构造函数接受一个JavaScript文件的URL,这个文件就是将要在worker线程中运行的代码。值得注意的是worker将会运行在与页面window对象完全不同的全局上下文中。

在worker线程中你可以运行大部分代码,但是有一些例外:

  • DOM对象
  • window对象的某些属性和方法
  • documen对象
  • parent对象

详细的信息可以参考:Functions and classes available to Web Workers

特殊种类的web workers

  • shared workers:可以被不同窗口的对各脚本运行,只要这些workers处于同一个主域。详细的用法会在之后的博文介绍

  • service workers :般作为web应用程序、浏览器和网络(如果可用)之间的代理服务。他们旨在(除开其他方面)创建有效的离线体验,拦截网络请求,以及根据网络是否可用采取合适的行动,更新驻留在服务器上的资源。他们还将允许访问推送通知和后台同步API。

    从网络安全的角度看,此woekers可以被利用成一个持久化XSS的工具。

官方文档