浏览器渲染进程

线程和进程

进程和线程的概念可以这样理解:

进程是一个工厂,工厂有它的独立资源–工厂之间相互独立–线程是工厂中的工人,多个工人协作完成任务–工厂内有一个或多个工人–工人之间共享空间

工厂有多个工人,就相当于一个进程可以有多个线程,而且线程共享进程的空间。

在这里插入图片描述
进程是cpu资源分配的最小单位(是能拥有资源和独立运行的最小单位,系统会给它分配内存)
线程是cpu调试的最小单位(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程。核心还是属于一个进程。)
浏览器是多进程的
在这里插入图片描述
浏览器是多进程的,每打开一个tab页,就相当于创建了一个独立的浏览器进程。

浏览器包含的进程:

1.Browser进程:浏览器的主进程(负责协调i,主控)

  • 负责浏览器的页面显示,与用户交互,如前进,后退等
  • 负责各个页面的管理,创建和销毁其他进程
  • 网络资源的管理,下载
  • 将Rendered进程得到的内存的Bitmap,绘制到用户界面上

2.第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建

3.GPU进程:最多一个,用户3D绘制等
4.浏览器渲染进程(浏览器内核或者Render进程,内部时多线程的),默认每个Tab页面一个进程,互部影响,主要作用为:

  • 页面渲染,运行脚本,事件处理等

在浏览器中打开一个网页就相当于新起了一个进程(进程内部有自己的多线程)

浏览器渲染进程(前端重点)

1)浏览器渲染进程浏览器内核,Render进程(内部是多线程的),默认的每个Tab页面一个进程,互不影响。
2)浏览器是多进程的,每打开一个Tab页就相当于创建了一个渲染进程,每个渲染进程又是多线程的。
其中,以下都是在渲染进程中进行的

  • 页面的渲染
  • 脚本执行
  • 任务队列轮询
一、渲染进程中主要的常驻线程:
1.GUI渲染线程
  • 负责渲染浏览器界面,解析HTML、CSS,构建DOM树和RenderObject树,然后布局和绘制页面。
  • 当页面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会被执行。
2.JS引擎线程
  • 也称为JS内核,负责处理JavaScript脚本程序(例如V8引擎)
  • JS引擎线程负责解析JavaScript脚本,运行代码。
  • JS引擎一直等待着队列中的任务的到来,然后加以处理,浏览器无论什么时候只有一个js线程在运行js程序,JS是单线程的(由于每个Tab页面都是一个独立的进程,且每个页面浏览器渲染进程(Render)都会有一个JS引擎线程,因此每个Tab页面之间的JS引擎线程是互不影响的。

GUI线程和JS引擎线程是互斥的,当JS引擎线程执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时才立即执行,如果JS执行时间过长,那么就很容易引起页面渲染被堵塞。

3.事件触发线程
  • 归属于浏览器而不是JS引擎,用来控制事件循环(可以理解为JS引擎自己忙不过来,需要浏览器另开线程协助)
  • 当JS引擎执行代码块如setTimeout时(也可以来自浏览器内科的其他线程,如鼠标点击,Ajax异步请求等),会将对应的任务添加到事件线程中。
  • 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。
  • 注意,由于JS的单线程关系,所以这些待处理的事件都得排队等待JS引擎处理
4.定时触发器线程
  • 就是传说中setTimeout和setInterval所在的线程
  • 浏览器定时计数器并不是由javascript引擎计数的(因为javascript引擎室单线程的,如果处于阻塞线程状态会影响计时的准确)
5.异步http请求线程
  • 在XMLHttpRequst在连接后通过浏览器新建一个线程请求
  • 将检索到状态的变更时,如果设置有回调函数,异步线程就尝试状态变更事件,将这个回调再放入事件队列中,再由javascript引擎执行
6.总结渲染进程

在这里插入图片描述

二、Browser主线程和浏览器内核(渲染进程)的通信过程

打开一个浏览器,可以看到:任务管理器出现可2个进程(一个主进程,一个是打开Tab页的渲染进程);

  • Browser主进程受到用户的请求,手下需要获取页面内容(如通过网络下载资源),随后将该任务通过RendererHost接口传递给Render渲染进程
  • Render渲染进程的Renderer接口受到信息,简单解析后,交给渲染线程GUI,然后开始渲染
  • GUI线程接收到请求,加载网页并解析网页,这其中可能需要Browser主线程获取资源和需要GPU进程来帮助渲染
  • 当然可能会有JS线程操作DOM(这可能会造成回流和重绘)
  • 最后Render渲染进程将结果传递给Browser主线程
  • Browser主线程接收到结果并将结果绘制出来
  • 在这里插入图片描述
三、浏览器内核(渲染进程)中线程之间的关系
1.GUI渲染线程和JS引擎线程互斥
2.JS堵塞页面加载
3.CSS加载是否会堵塞dom树的渲染

1)css加载不会堵塞DOM树解析
2)会堵塞render树渲染(渲染时需要等css加载完毕,因为render树需要css信息)

render树就是根据可视化节点和css样式表结合诞生出来的树
所以一般把DOM树的结果解析完,把可以做的工作做完,然后等css加载完之后,再根据最终的css样式来渲染render树,这样可起到优化性能的作用。

五、总结浏览器的渲染过程

浏览器输入url,浏览器主进程接管,开一个下载线程,然后进行http请求(这里省略DNS解析、IP查询等),然后等待响应,获取内容,随后将内容通过RenderHost接口传给浏览器渲染进程(Render进程),浏览器渲染流程开始:

浏览器内核拿到内容之后,渲染大致可以划分如下:
1.解析HTML建立FOM树
2.解析CSS构建render树(将css代码解析构成CSSOM树,然后结合DOM树构成render树)
3.布局render树(Layout/reflow),负责各元素尺寸,位置的计算)
4.绘制render树(paint),绘制页面像素信息
5.浏览器会将各层信息发送给GPU,GPU会将各层合成(composite),显示再屏幕上渲染完毕之后就是load事件了(即渲染完毕之后,会触发load事件),之后就是自己的JS逻辑处理了(这里省去详细的步骤)

当onload事件触发时,页面上所有的DOM、样式表、脚本、图片都已经加载完毕了

参考文章:

浏览器的渲染机制

Guess you like

Origin blog.csdn.net/weixin_46872121/article/details/111885325