前置概念
进程:CPU资源分配的最小单位,是能拥有资源和独立运行的最小单位,不同进程之间不会共享资源
线程:CPU调度的最小单位,一个进程可以拥有多个线程,多个线程之间可以共享资源
浏览器中的进程
浏览器是多进程的,并且每一个tab页为一个独立的进程
浏览器主进程
浏览器的主进程(只有一个),负责协调、主控。
负责浏览器的界面显示,用户交互,网址输入、前进、后退等。
负责各个页面的创建和销毁。
将页面内容写入到浏览器内存中,最后将图像显示在屏幕上。
文件存储等功能
浏览器主进程中的线程:
UI线程:该线程是程序运行的主线程,是程序的入口点,用来处理用户交互(如监听用户输入、前进后退等)。同时,会分发任务给其他相应线程去执行。
IO线程:处理
Browser
进程与其他进程进行进程间通信,下载Renderer
进程所需的资源文件等。File线程:读取磁盘文件,下载文件到磁盘等。
数据库线程:进行一些数据库操作,例如保存
Cookie
到数据库历史记录线程
http服务代理线程
渲染进程
默认情况下,一个 tab
配一个渲染进程。主要的作用是页面渲染、脚本执行、事件处理
渲染进程中的常用线程
1.JS引擎线程
JS引擎线程负责解析
JavaScript
脚本,然后运行代码。JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个
Tab页
(render进程)中无论什么时候都只有一个 JS线程 在运行JS程序。GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。这里是react v15版本之前页面状态频繁更新导致渲染卡顿的原因,执行一次状态更新占用了JS执行超过16ms,执行完成后才回去允许渲染线程,就这样反复就导致了页面卡顿
2.HTTP请求线程
XMLHttpRequest
在连接后会通过浏览器新开一个线程来进行请求(异步)。检测到状态变更时,如果设置有回调函数,异步线程就会产生状态变更事件,将这个回调放入事件队列中。再交由
JavaScript引擎
执行。
3.定时器触发线程
浏览器的定时器并不是由
JavaScript引擎
来计数的。(因为JavaScript引擎
是单线程的,如果处于阻塞线程状态的话就会影响计时器的准确性)因此通过单线程来计时并触发定时。(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
注意:W3C的HTML标准规范中,对于setTimeout()设置的时间低于4ms的,都按照4ms来算
4.事件处理线程
事件处理线程归属于浏览器而不是JS引擎,用来控制事件循环。(JS引擎自己都忙不过来,需要浏览器另外开辟线程来协助处理)。
当JS引擎执行代码时(如果其中有异步、鼠标点击事件等),会将对应任务添加到事件现场中。
当对应的事件符合条件并被触发时,事件处理线程会把事件添加到待处理队列的尾部,等待JS引擎的处理。
注意:由于JS是单线程的原因,所以这些待处理队列中的事件都是排队等待JS引擎处理(等到JS引擎空闲的时候再去执行)
5.GUI渲染线程
GUI渲染线程:负责渲染浏览器界面,解析HTML、CSS,构建DOM树和 Render 树,进行布局和绘制等。
触发执行:当页面需要重绘或由于某种操作引发回流(重排)时,GUI渲染线程就会触发
注意:GUI渲染线程与JS引擎是互斥的,当JS引擎执行时,GUI线程会被挂起,GUI更新会被保存在一个队列中直到JS引擎空闲时才会继续执行。
GPU进程
用于3D绘制,将开启了3D绘制的元素渲染由CPU转向GPU,最多一个
网络进程
主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程中,现在独立出来,成为一个单独的进程。
插件进程
每种类型的插件对应一个进程,仅当使用该插件是才创建。
总结
以上浏览器的进程与线程的基本认识,浏览器是一个多进程的应用,其中对于前端来说最为重要的和要理解的是渲染进程,渲染进程是一个多线程的进程,渲染进程中,GUI渲染进程和JS引擎线程是互斥的,因此JS引擎执行js事件过程时会产生渲染停滞的问题。
评论区