一、首页了解一下,进程和线程的区别
1、关于几个1
进程-->CPU 分配资源的最小单位,同一个时间内单个 CPU 只能运行一个进程,单个 CPU 一次只能运行一个任务;
线程-->CPU 调度的最小单位,一个进程里面包含多个线程。
2、进程和线程的理解
- 进程是一个工厂,工厂有它的独立资源
- 工厂之间相互独立
- 线程是工厂中的工人,多个工人协作完成任务
- 工厂内有一个或多个工人
- 工人之间共享空间
结合进程和线程解释
- 工厂的资源 -> 系统分配的内存(独立的一块内存)
- 工厂之间的相互独立 -> 进程之间相互独立
- 多个工人协作完成任务 -> 多个线程在进程中协作完成任务
- 工厂内有一个或多个工人 -> 一个进程由一个或多个线程组成
- 工人之间共享空间 -> 同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)
3、最后再巩固下:
如果是windows电脑中,可以打开任务管理器,可以看到有一个后台进程列表。对,那里就是查看进程的地方,而且可以看到每个进程的内存资源信息以及cpu占有率。
注意:
- 不同进程之间也可以通信,不过代价较大
- 现在,一般通用的叫法:单线程与多线程,都是指在一个进程内的单和多。(所以核心还是得属于一个进程才行)
二、浏览器是多进程的
理解了进程与线程了区别后,接下来对浏览器进行一定程度上的认识:(先看下简化理解)
- 浏览器是多进程的
- 浏览器之所以能够运行,是因为系统给它的进程分配了资源(cpu、内存)
- 简单点理解,每打开一个Tab页,就相当于创建了一个独立的浏览器进程。
注意:在这里浏览器应该也有自己的优化机制,有时候打开多个tab页后,可以在Chrome任务管理器中看到,有些进程被合并了
(所以每一个Tab标签对应一个进程并不一定是绝对的)
01-浏览器常见的进程
现代浏览器是多进程架构,页面的加载、渲染和交互是由多个进程配合完成。以 Chrome 为例,其主要的进程架构如下:
1、浏览器主进程
Browser进程:浏览器的主进程(负责协调、主控),只有一个;
作用有:
1、负责浏览器界面显示,与用户交互,子进程管理,同时提供存储等功能,如前进,后退等;
2、负责各个页面的管理,创建和销毁其他进程;
3、将Renderer进程得到的内存中的Bitmap,绘制到用户界面上;
4、网络资源的管理,下载等;
2、插件进程
第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建,主要是负责插件的运行。
因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
3、GPU 进程
GPU进程:最多一个,用于3D绘制等;
Chrome 刚开始发布的时候是没有 GPU 进程的;
GPU 的使用初衷是为了实现 3D CSS 的效果;
随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求;
最后,Chrome 在其多进程架构上也引入了 GPU 进程;
4、网络进程
主要负责页面的网络资源加载。
之前是作为一个模块运行在浏览器主进程里面的,直至最近才独立出来,成为一个单独的进程。
5、渲染进程(eventloop机制用到地方)
浏览器渲染进程(浏览器内核)(Renderer进程,内部是多线程的):
主要作用为:
01、页面渲染:核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页;
02、脚本处理,事件处理,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中;
03、默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程;
04、出于安全考虑,渲染进程都是运行在沙箱模式下,无法访问系统资源。
02-浏览器多进程的优势
相比于单进程浏览器,多进程有如下优点:
- 避免单个page crash影响整个浏览器
- 避免第三方插件crash影响整个浏览器
- 多进程充分利用多核优势
- 方便使用沙盒模型隔离插件等进程,提高浏览器稳定性
简单点理解:如果浏览器是单进程,那么某个Tab页崩溃了,就影响了整个浏览器,体验有多差;同理如果是单进程,插件崩溃了也会影响整个浏览器;而且多进程还有其它的诸多优势。。。
当然,内存等资源消耗也会更大,有点空间换时间(利用空闲内存,增加页面流畅度,减少渲染时间)的意思。
03-重点是浏览器内核(渲染进程,即上面常见进程,5、渲染进程(eventloop机制用到地方))
重点来了,我们可以看到,上面提到了这么多的进程,那么,对于普通的前端操作来说,最终要的是什么呢?答案是渲染进程
可以这样理解,页面的渲染,JS的执行,事件的循环,都在这个进程内进行。接下来重点分析这个进程
请牢记,浏览器的渲染进程是多线程的(这点如果不理解,请回头看进程和线程的区分)
终于到了线程这个概念了?,好亲切。那么接下来看看它都包含了哪些线程(列举一些主要常驻线程):
- GUI渲染线程
- 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
- 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行
- 注意,GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
- JS引擎线程
- 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
- JS引擎线程负责解析Javascript脚本,运行代码。
- JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序
- 同样注意,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
- 事件触发线程
- 归属于浏览器而不是JS引擎,用来控制事件循环(可以理解,JS引擎自己都忙不过来,需要浏览器另开线程协助)
- 当JS引擎执行代码块如setTimeOut时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件线程中
- 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
- 注意,由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)
- 定时触发器线程
- 传说中的
setInterval
与setTimeout
所在线程 - 浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)
- 因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
- 注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
- 传说中的
- 异步http请求线程
- 在XMLHttpRequest在连接后是通过浏览器新开一个线程请求
- 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。
浏览器渲染进程(浏览器内核)图解