浏览器的进程都有哪些?

162 阅读5分钟

浏览器的进程

浏览器是多进程的,每打开一个tab页就会新增一个进程,如果我们使用Chrome打开很多标签页不关,电脑会越来越卡

浏览器包含哪些进程

Browser进程

  • 浏览器的主进程,用于管理协调各个其他进程
  • 负责浏览器的界面显示,与用户的交互以及页面的前进,后退等
  • 网络资源的下载与管理

第三方插件进程

  • 每种类型的插件对应一个进程,当使用该插件时才创建

GPU进程

  • 该进程也只有一个,用于3D绘制等等

渲染进程

  • 即通常所说的浏览器内核(Renderer进程,内部是多线程)
  • 每个tab一个渲染进程,互不影响
  • 主要作用是进行页面渲染,脚本执行,事件处理

重点:renderer进程

页面的渲染,js的执行,事件的循环,都在渲染进程内执行,所以我们要重点了解渲染进程

GUI渲染进程:重点

  1. 负责渲染浏览器的页面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等

    • 解析HTML文件(发送过来的HTML文件先是01比特流,由计算机转换为字符串)再转为浏览器认识的节点,生成DOM树
    • 解析CSS,生成CSSOM(css规则树)
    • 把DOM树和CSSOM结合就得到了rendering树:渲染树的作用就是将DOM树与CSSOM的内容一一结合并且捕获可见内容
  2. 进行重绘(Repaint):当我们修改了元素的颜色或者背景色就会发生重绘。(重绘就是房子重新上色)

  3. 进行回流(Reflow):当我们修改了元素的尺寸就会发生回流。(回流是房子拆了重建)

    浏览器对回流和重绘的优化:浏览器会维护一个重绘回流的队列,当触发一定的阈值就会清空队列进行批处理

    但是调用以下方法浏览器会立刻清空队列,执行回流和重绘:offsetLeft, offsetTop, offsetWidth, offsetHeight等

  4. 回流的成本比重绘高,我们要避免回流和重绘

    1.避免频繁操作样式:通过增改类名一次性改变style 2.避免频繁操作DOM:脱离文档流、使用文档碎片(document fragment)、隐藏后修改完再显示  3.避免多次访问上面的属性与方法  4.复杂动画:使用绝对定位脱离文档流   5.触发CSS3硬件加速:使用transfrom,opactity,filters,Will-change

  5. GUI线程与js引擎线程是互斥的

    • js引擎线程在执行的时候GUI线程被挂起
    • GUI更新会保存在一个队列中等待js引擎线程空闲时立即执行

js引擎线程

  1. js引擎线程就是js内存,用于处理JavaScript脚本(例如V8引擎)

  2. js引擎一直等待任务队列中任务的到来,然后加以处理

    为什么说js的单线程的?

    1.浏览器同时只能有一个js引擎在执行js任务

    2.一个renderer进程无论何时只有一个js引擎线程

  3. GUI渲染线程与js引擎线程是互斥的,js引擎线程会阻塞GUI渲染线程

    • 就是我们常遇到的js执行时间过长,造成页面的渲染不连贯,导致页面渲染加载阻塞(就是加载慢)
    • 例如浏览器渲染的时候遇到<script>标签,就会停止GUI的渲染,然后js引擎线程开始工作,执行里面的js代码,等js执行完毕,js引擎线程停止工作,GUI继续渲染下面的内容。所以如果js执行时间太长就会造成页面卡顿的情况

    怎么样解决上述问题呢?

    可以把script标签放在最后,也有使用async和defer属性,async:异步加载script,加载完毕立即执行,执行时阻塞渲染,执行顺序可能改变;defer:异步加载script,加载完成等待渲染完成再执行,一定按照原本的顺序执行

事件触发线程

  1. 属于浏览器而不是js引擎线程,用来控制事件循环和管理事件队列(Task queue)
  2. 当js执行遇到事件监听和异步函数(如绑定鼠标点击事件,setTimeout,Ajax异步请求等),会通过事件触发线程将事件添加到对应的线程中,等异步任务有结果,便把他们的回调函数添加到事件队列中,等待js引擎线程空闲时处理
  3. 当对应事件符合触发条件时,该线程将此事件添加到待处理队列末尾,等待js引擎空闲时处理
  4. 因为js是单线程,所以这些待处理队列中的事件都得排队等待js引擎处理

定时触发线程

1.专门用于监控setInterval与setTimeout的线程

2.浏览器的定时器不是js引擎计时的

3.当定时器到时,定时触发线程就会把此定时器的回调函数交给事件触发进程,由事件触发进程将这个定时器的回调放到task queue(宏任务队列)中等待js空闲时执行

异步http请求线程

1.每次新建XMLHttpRequest就新建一个异步http请求线程

2.当这个异步请求状态变化就把响应的回调交给事件触发进程,由事件触发进程将这个异步请求的回调放到task queue(微任务队列)中等待js空闲时执行

为什么要这样控制事件触发?

为了让浏览器上的所有线程的工作都很单一且独立,符合单一原则

定时触发线程只管理定时器且只关注定时不关心结果,定时结束就把回调扔给事件触发线程

异步http请求线程只管理http请求同样不关心结果,请求结束把回调扔给事件触发线程

事件触发线程只关心异步回调入事件队列

参考: 「硬核JS」一次搞懂JS运行机制 - 掘金 (juejin.cn)