浏览器 进程/线程 介绍

发布于 2023-10-10 12:55:46 字数 3917 浏览 29 评论 0

进程 线程

浏览器多进程,每打开一个 tab 就多一个进程,browser 进程 浏览器的主进程 只有一个

  • 负责各个页面的管理,创建和销毁其他进程
  • 网络资源的管理,下载等
  • 负责浏览器界面显示,与用户交互。如前进,后退等

GPU 进程:最多一个,用于 3D 绘制等

浏览器渲染进程(浏览器内核)(Renderer 进程,内部是多线程的

[页面的渲染,JS 的执行,事件的循环] 都在这个进程里,默认每个 Tab 页面一个进程,互不影响,主要作用为 页面渲染,脚本执行,事件处理等

多进程的优势

  • 防止单 page crash 影响整个浏览器
  • 避免第三方插件 crash 影响整个浏览器
  • 多进程充分利用多核优势
  • 方便使用沙盒模型隔离插件等进程,提高浏览器稳定性

渲染进程内部是有多线程的看看哪些线程吧

1. GUI 渲染线程

  1. 负责渲染浏览器界面,解析 HTML,CSS,构建 DOM 树和 RenderObject 树,布局和绘制等。
  2. 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow) 时,该线程就会执行
  3. GUI 渲染线程与 JS 引擎线程是互斥的 当 JS 引擎执行时 GUI 线程会被挂起(相当于被冻结了),GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即被执行。

2. JS 引擎线程

  1. 也称为 JS 内核,负责处理 Javascript 脚本程序
  2. JS 引擎线程负责解析 Javascript 脚本,运行代码。
  3. GUI 渲染线程与 JS 引擎线程是互斥的,所以如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。

3. 事件触发线程

  1. 当 JS 引擎执行代码块如 setTimeOut 时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX 异步请求等),会将对应任务添加到事件线程中
  2. 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待 JS 引擎的处理

由于 JS 的单线程关系,所以这些待处理队列中的事件都得排队等待 JS 引擎处理(当 JS 引擎空闲时才会去执行)

4. 定时触发器线程

传说中的 setInterval 与 setTimeout 所在线程,为什么要单独的定时器线程?因为 JavaScript 引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确,因此很有必要单独开一个线程用来计时。

5. 异步 http 请求线程

在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求,将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由 JavaScript 引擎执行。

WebWorker

  • 创建 worker 时,js 引擎向浏览器申请一个子线程, 子线程完全由浏览器控制 所以不能操作 dom
  • js 引擎线程与 worker 子线程通过特定的方式通信,需要通过序列化对象来与线程交互特定的数据
  • JS 引擎是单线程的,这一点的本质仍然未改变,Worker 可以理解是浏览器给 JS 引擎开的外挂,专门用来解决那些大量计算问题。

WebWorker 与 SharedWorker

WebWorker 只属于某个页面,不会和其他页面的 Render 进程(浏览器内核进程)共享,所以 Chrome 在 Render 进程中(每一个 Tab 页就是一个 render 进程)创建一个新的线程来运行 Worker 中的 JavaScript 程序。

SharedWorker 是浏览器所有页面共享的,不能采用与 Worker 同样的方式实现,因为它不隶属于某个 Render 进程,可以为多个 Render 进程共享使用,sharedWorker 由单独的进程管理, WebWorker 只是属于 render 进程下的一个线程。

  • css 加载是否会阻塞 dom 树渲染?
  • css 是由单独的下载线程异步下载的。
  • css 加载不会阻塞 DOM 树解析(异步加载时 DOM 照常构建)

但会阻塞 render 树渲染(渲染时需等 css 加载完毕,因为 render 树需要 css 信息)

普通图层和复合图层

GPU 中每个复合图层是单独绘制的 所以不相互影响,普通文档流内可以理解成一个复合图层 这里称为默认复合层,里面不管添加多少元素,其实都是在同一个复合图层中),absolute fixed 布局 脱离文档流 还在这个复合图层。

通过硬件加速,声明一个新的复合图层 他会单独分配资源, 当然也会脱离文档流,这样这个复合图层怎么改变,也不会影响默认复合层的重排重绘。

如何生成新的复合图层

硬件加速

最常用的方式:translate3d、translateZ,opacity 属性/过渡动画(需要动画执行的过程中才会创建合成层,动画没有开始或结束后元素还会回到之前的状态),<video><iframe><canvas><webgl>等元素

其它,譬如以前的 flash 插件

absolute 和硬件加速的区别

absolute 虽然脱离文档流 但是仍然在默认复合层内,就算 absolute 中信息改变时不会改变普通文档流中的 render 树,但是浏览器最终绘制的时候还是会整个复合层绘制,所以 absolute 中信息的改变,仍然会影响整个复合层的绘制。

硬件加速是在另一个复合层中,他的信息改变不会引起原来的复合层改变(当然,内部肯定会影响属于自己的复合层)仅仅是引发最后的合成(输出视图)

复合图层的作用

一般一个元素开启硬件加速后会变成复合图层,可以独立于普通文档流中,改动后可以避免整个页面重绘,提升性能量,但是不要大量使用复合图层,否则由于资源消耗过度,页面反而会变的更卡

Event loop

JS 中分为两种任务类型:macrotask 和 microtask 在 ECMAScript 中,microtask 称为 jobs,macrotask 可称为 task,macrotask 中的事件都是放在一个事件队列里面,是由事件触发线程维护。

可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)

  1. 每一个 task 会从头到尾将这个任务执行完毕,不会执行其它
  2. 浏览器为了能够使得 JS 内部 task 与 DOM 任务能够有序的执行,会在一个 task 执行结束后,在下一个 task 执行开始前,对页面进行重新渲染 (task->渲染->task->...)

microtask 中所有微任务都是添加到微任务队列中,等待当前 macrotask 执行完毕后 这个队列由 js 引擎线程自己维护

  1. 在当前 task 任务后,下一个 task 之前,在渲染之前
  2. 所以它的响应速度相比 setTimeout(setTimeout 是 task)会更快,因为无需等渲染
  3. 在某一个 macrotask 执行完后,就会将在它执行期间产生的所有 microtask 都执行完毕(在渲染前)

microtask:Promise,process.nextTick 等

macrotask:主代码块,setTimeout,setInterval 等(可以看到,事件队列中的每一个事件都是一个 macrotask)

总结一下运行机制

  1. 执行一个宏任务栈中(没有就从事件队列中获取)
  2. 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  3. 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行
  4. 当前宏任务执行完毕,开始检查渲染,然后 GUI 线程接管渲染
  5. 渲染完毕后,JS 线程继续接管,开始下一个宏任务(从事件队列中获取)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

与他有关

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文