前文中,已经多次提到了浏览器是多进程的,JS是单线程的,具体要怎么理解呢?
一、进程和线程
进程和线程是涉及到操作系统如何调度资源(CPU 、内存、磁盘)的概念,先抛出概念:进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元。
进程更倾向于内存管理的概念,线程更倾向于cpu的运行。
- 一个程序可以有不止一个的进程;
- 一个进程可以没有线程,作为空进程存在,但是由于里面没有线程,cpu在这里无法得到执行;cpu的执行依附于线程
线程无法脱离进程而存在。
二、浏览器进程
浏览器作为一个计算机应用程序,如果打开浏览器默认进入一个空白页,相当于新起了一个浏览器的主进程和GPU进程,如果再打开一个标签页,则又创建了一个渲染进程。
调出chrome的任务管理器(shift+esc或在标签栏空白处点右键),可以看到:
- 浏览器是多进程的
- 浏览器之所以能够运行,是因为系统给它的进程分配了资源(cpu、内存)
- 浏览器每打开一个Tab页,就相当于创建了一个独立的浏览器进程。
浏览器多进程的优点:
- 避免单个页面崩溃影响整个浏览器
- 避免第三方插件崩溃影响整个浏览器
- 多进程充分利用多核优势
- 方便使用沙盒模型隔离插件等进程,提高浏览器安全性
简单的说,浏览器多进程避免了一个页面或一个插件的崩溃导致整个浏览器的崩溃,大大改善了用户体验。
PS:“沙盒”技术的实践运用流程是:让疑似病毒文件的可疑行为在虚拟的“沙盒”里充分表演,“沙盒”会记下它的每一个动作;当疑似病毒充分暴露了其病毒属性后,“沙盒”就会执行“回滚”机制:将病毒的痕迹和动作抹去,恢复系统到正常状态。如果您还不懂,那说的再简单一些。想象一下,在一个装满了平整细沙的盒子里,我们可以尽情随意地在上面作画、涂写,无论画的好坏,最后轻轻一抹,沙盒又回到了原来的平整状态。沙盒的魅力就在于他允许你出错,还可以给你改正的机会。
浏览器多进程的缺点:
浏览器多进程提高用户体验的同时是要付出代价的,那就是对系统资源的消耗加大,特别是内存的消耗。
三 、浏览器有哪些进程
1、Browser进程:
浏览器的主进程(负责协调、主控),只有一个,相当于浏览器的大脑,作用有
- 负责浏览器界面显示,与用户交互,如前进,后退等;
- 负责各个页面的管理,创建和销毁其他进程;
- 将渲染线程得到的内存中的位图渲染到用户界面上;
- 网络资源的管理,下载等。
2、第三方插件进程:
每种类型的插件对应一个进程,仅当使用该插件时才创建。
3、GPU进程:
最多一个,负责3D绘制,只有当该页面使用了硬件加速才会使用它,来渲染页面。否则的话,不使用这个进程,而是用Browser进程来渲染页面。
4、浏览器渲染进程(Renderer进程)
也称浏览器内核、Renderer进程(内部是多线程的),默认每个Tab页面一个进程,互不影响。主要作用为页面渲染,脚本执行,事件处理,任务队列轮询等。
浏览器有时会将多个渲染进程合并(譬如打开多个空白标签页后,会发现多个空白标签页被合并成了一个进程)。
四、前端重点:渲染进程(浏览器内核)
现在我们再来捋一下进程和线程,浏览器是多进程的,每打开一个tab页相当于创建了一个渲染进程,每个渲染进程是又多线程的。
页面的渲染,JS的执行,事件的循环,都在渲染进程中进行。
渲染进程中的主要常驻线程:
1、GUI渲染线程
- 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
- 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。
2、JS引擎线程
- 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
- JS引擎线程负责解析Javascript脚本,运行代码。
- JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序,JS是单线程的。
PS:GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行;如果JS执行的时间过长,会导致页面渲染被阻塞。
3、事件触发线程
接受浏览器里面的操作事件响应。如在监听到鼠标、键盘等事件的时候, 如果有事件处理函数,就将对应的任务压入任务队列(添加到待处理队列的队尾),等待JS引擎的处理。
事件触发线程管理着一个任务队列。
4、定时触发器线程
- setInternal与setTimeout所在线程
- 浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)
- 因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
5、异步http请求线程
- 在XMLHttpRequest在连接后是通过浏览器新开一个线程请求
- 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。
Browser进程和渲染进程的通信过程
就像前文中那样新打开谷歌浏览器,并打开任务管理器,可以看到:任务管理器中出现了三个进程,来了解一下浏览器的主进程和渲染进程是怎样通信的:
- Browser进程收到用户请求(输入网址并回车),首先需要获取页面内容(譬如通过网络下载资源),随后将该任务通过RendererHost接口传递给Render进程。
- Renderer进程的Renderer接口收到消息,简单解释后,交给渲染线程,然后开始渲染。
① 渲染线程接收请求,加载网页并渲染网页,这其中可能需要Browser进程获取资源和需要GPU进程来帮助渲染;
② 可能会有JS线程操作DOM(这样可能会造成回流并重绘);
③ 最后Render进程将结果传递给Browser进程; - Browser进程接收到结果并将结果绘制出来