浏览器相关

270 阅读9分钟

进程与线程之间的关系

进程是CPU资源分配的最小单位,是能拥有资源和独立运行的最小单位。(系统会给他分配内存)

线程是CPU调度的最小单位。(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)

参考:juejin.cn/post/684490…

浏览器是多进程的。浏览器之所以能够运行,是因为系统给他的进程分配了资源。

css什么情况下会阻塞dom树的渲染

如果页面中同时存在css和js,并且js在css后面,两个都放在head中,则DOMContentLoaded事件会在css加载完后才执行。

JS是单线程的,加载时间过长会阻塞页面的渲染,造成卡顿,因为JS引擎线程和GUI渲染线程是互斥的,JS引擎线程工作时,GUI线程会被挂起。

因此,可以用WebWorker在后台线程中运行脚本,它运行在另一个全局上下文中,不同于当前的window,因此,使用 window快捷方式获取当前全局的范围 (而不是self) 在一个 Worker 内将返回错误。JS引擎线程和webworker线程通过postMessage API进行通信,所以有非常耗时的工作,可以交给webworker线程。这并不影响JS引擎是单线程的,因为webworker是浏览器新开的线程,相当于给JS引擎开的额外挂。

WebWorker 和 SharedWorker的区别

  • WebWorker只属于某一个页面,不会和其他页面的Renderer进程共享。一个页面就是一个Renderer进程。
  • SharedWorker是浏览器所有页面共享的,可以为多个Renderer进程共享使用。Chrome浏览器为SharedWorker单独创建一个进程来运行JavaScript程序,在浏览器中每个相同的JavaScript只存在一个SharedWorker进程,不管它被创建多少次。
  • 本质上就是进程和线程的区别。SharedWorker由独立的进程管理,WebWorker只是属于render进程下的一个线程。

浏览器的多进程

1.Browser进程(浏览器的主进程)

2.第三方插件进程

3.GPU进程(最多一个)

4.浏览器渲染进程(浏览器的内核),内部多线程,主要负责页面渲染,脚本执行,事件处理。在浏览器中打开一个网页,相当于新建了一个进程。

浏览器多进程的优点

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

Renderer进程(浏览器内核)

对前端来说,最重要的进程是渲染进程。在这个进程中会进行页面的渲染,JS的执行,事件的循环。 主要包括:

  • GUI渲染线程:负责渲染浏览器界面,解析HTML,CSS,构建DOM树,布局树,生成绘制列表。回流和重绘也会触发该线程的执行。注意,GUI渲染线程与JS引擎线程是互斥的, 当JS引擎线程执行时,GUI线程会被挂起,GUI更新会被保存在一个队列中,直到JS引擎线程更新时才会被执行。
  • JS引擎线程:主要处理JS脚本程序,比如V8引擎。一个渲染进程中无论什么时候都只有一个JS线程在运行JS程序。同样,GUI渲染线程与JS引擎线程是互斥的。
  • 事件触发线程:归属于浏览器而不是JS引擎,用来控制事件循环。当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。
  • 定时触发器线程:浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确)。注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
  • 异步http请求线程:在XMLHttpRequest连接后是通过浏览器新开一个线程请求。将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。

浏览器进程与Renderer进程的通信

  • Browser进程收到用户请求,首先需要获取页面内容(譬如通过网络下载资源),随后将该任务通过RendererHost接口传递给Render进程。
  • Renderer进程的Renderer接口收到消息,简单解释后,交给渲染线程,然后开始渲染。渲染线程接收请求,加载网页并渲染网页,这其中可能需要Browser进程获取资源和需要GPU进程来帮助渲染。当然可能会有JS线程操作DOM(这样可能会造成回流并重绘)。最后Render进程将结果传递给Browser进程。
  • Browser进程接收到结果并将结果绘制出来。

DOMContentLoaded与load的先后顺序

DOMContentLoaded:仅当DOM加载完成,不包括样式。

load:渲染完成。

DOMContentLoaded->load。

普通图层与复合图层

浏览器渲染的图层一般分为普通图层和复合图层。普通文档流内可以理解为一个复合图层(这里称为默认复合层,里面不管添加多少元素,其实都是在同一个复合图层中)。absolute布局(fixed也一样),虽然可以脱离普通文档流,但它仍然属于默认复合层。然后,可以通过硬件加速的方式,声明一个新的复合图层,它会单独分配资源 (当然也会脱离普通文档流,这样一来,不管这个复合图层中怎么变化,也不会影响默认复合层里的回流重绘)。GPU中,各个复合图层是单独绘制的,所以互不影响, 这也是为什么某些场景硬件加速效果一级棒。

如何变成复合图层,进行硬件加速?

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

复合图层的作用

采用硬件加速,不占用主线程资源,避免重流和重绘。

absolute和硬件加速的区别?

absolute虽然可以脱离普通文档流,但无法脱离默认复合层。所以,就算absolute中信息改变时不会改变普通文档流中render树, 但是,浏览器最终绘制时,是整个复合层绘制的,所以absolute中信息的改变,仍然会影响整个复合层的绘制。 (浏览器会重绘它,如果复合层中内容多,absolute带来的绘制信息变化过大,资源消耗是非常严重的)。而硬件加速直接就是在另一个复合层了(另起炉灶),所以它的信息改变不会影响默认复合层 (当然了,内部肯定会影响属于自己的复合层),仅仅是引发最后的合成(输出视图)。

硬件加速时要使用z-index,避免层爆炸问题。

具体的原理是这样的: webkit CSS3中,如果这个元素添加了硬件加速,并且index层级比较低, 那么在这个元素的后面其它元素(层级比这个元素高的,或者相同的,并且releative或absolute属性相同的), 会默认变为复合层渲染,如果处理不当会极大的影响性能。

事件循环时,一个宏任务执行结束后,先执行微任务,然后渲染页面,再进行下一个宏任务。

宏任务是由事件触发线程维护的,微任务是由JS引擎线程维护的。

DNS解析过程

    1. 首先系统会检查浏览器本地缓存有没有这个域名对应的解析过的IP地址。
    1. 如果用户的浏览器缓存中没有,就去检查操作系统缓存即本地的Host文件。
    1. 如果本地Host文件中没有,操作系统就把域名发送给本地域名服务系统即Local DNS。
    1. 如果仍然没有命中,就发给Root Server域名服务器请求解析。
    1. Root Server会返回给本地域名服务器一个所查找的域的gTLD主域名服务器地址。
    1. 本地服务器再向所返回的这个gTLD服务器发送请求。
    1. 接受请求的gTLD服务器查找并返回此域名对应的Name Server域名服务器的地址。
    1. Name Server域名服务器会查找域名与IP地址的关系映射表,连同一个TTL值返回给DNS Server。
    1. Local DNS会缓存所返回的该域名的IP和TTL值,缓存时间由TTL控制。
    1. 把解析的结果返回给用户。用户根据TTL值缓存在本地系统缓存中。

CDN原理

参考文章

    1. 当用户点击网站页面上的内容URL,经过本地DNS系统解析,DNS系统会最终将域名的解析权交给CNAME指向的CDN专用DNS服务器。
    1. CDN的DNS服务器将CDN的全局负载均衡设备IP地址返回用户。
    1. 用户向CDN的全局负载均衡设备发起内容URL访问请求。
    1. CDN全局负载均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备,告诉用户向这台设备发起请求。
    1. 区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务,选择的依据包括:根据用户IP地址,判断哪一台服务器距用户最近;根据用户所请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力。基于以上这些条件的综合分析之后,区域负载均衡设备会向全局负载均衡设备返回一台缓存服务器的IP地址。
    1. 全局负载均衡设备把服务器的IP地址返回给用户
    1. 用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容传送到用户终端。如果这台缓存服务器上并没有用户想要的内容,而区域均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉到本地。