浏览器运行机制

一 线程与进程

进程是系统资源分配的最小单位(即系统以进程为最小单位分配内存空间,同时进程是能独立运行的最小单位)

线程是系统调度的最小单位(即系统以线程为单位分配cpu中的核。)

二 浏览器的多进程

浏览器是多进程的。可以打开chrome浏览器的任务管理器。

三 浏览器的各个进程及作用介绍

Browser进程 : 是浏览器的主进程,负责主控,协调,只有一个,可以看做是浏览器的大脑。

  • 负责下载页面的网络文件
  • 负责将renderer进程得到的存在内存中的位图渲染(显示)到页面上
  • 负责创建和销毁tab进程(renderer进程)
  • 负责与用户的交互

GPU进程 : 只有一个

  • 负责3D绘制,只有当该页面使用了硬件加速才会使用它,来渲染(显示)页面。否则的话,不使用这个进程,而是用Browser进程来渲染(显示)页面

渲染进程(renderer)又名浏览器内核,每个tab页面对应一个独立的renderer进程,内部有多个线程。

  • 负责脚本执行,位图绘制,事件触发,任务队列轮询等

第三方插件进程:每种类型的插件对应一个进程(只有插件在使用时)。

浏览器是多进程的好处非常明显,如果浏览器是单线程的话,则一个页面,一个插件的崩溃会导致整个浏览器崩溃,用户体验感会非常差。

缺点就是,占内存。

四 浏览器内核(渲染进程)

渲染进程是多线程的,以下是各个线程的名称及作用(仅列举常驻线程)。

  • js引擎线程:
    • 也称js内核,解析js脚本,执行代码
    • 与GUI线程互斥,即当js引擎线程运行时,GUI线程会被挂起,当js引擎线程结束运行时,才会继续运行GUI线程
    • 由一个主线程和多个web worker线程组成,由于web worker是附属于主线程,无法操作dom等,所以js还是单线程语言(在主线程运行js代码)
  • GUI渲染线程:
    • 用于解析html为DOM树,解析css为CSSOM树,布局layout,绘制paint
    • 当页面需要重排reflow,重绘repaint时,使用该线程
    • 与js引擎线程互斥
  • 事件触发线程
    • 当对应事件触发(不论是WebAPIs完成事件触发,还是页面交互事件触发)时,该线程会将事件对应的回调函数放入callback queue(任务队列)中,等待js引擎线程的处理
  • 定时触发线程
    • 对应于setTimeout,setInterval API,由该线程来计时,当计时结束,将事件对应的回调函数放入任务队列中
    • 当setTimeout的定时的时间小于4ms,一律按4ms来算
  • http请求线程
    • 每有一个http请求就开一个该线程
    • 当检测到状态变更的话,就会产生一个状态变更事件,如果该状态变更事件对应有回调函数的话,则放入任务队列中
  • 任务队列轮询线程
    • 用于轮询监听任务队列,以知道任务队列是否为空

html解析过程

html解析包含有一系列的步骤,过程为Bytes -> Characters -> Tokens -> Nodes -> DOM。最终将html解析为DOM树。

css解析过程

与html解析相似。Bytes -> Characters -> Tokens -> Nodes -> DOM。最终将css解析为css树

render树

遍历dom并寻找各个元素在css树中对应的样式,结合形成render树。

由DOM树与CSS树结合形成的渲染树(其中无法显示的元素,如script,head元素或diplay:none的元素,不会在渲染树中,也就最终不会被渲染出来),页面的布局,绘制都是以render树为依据。

回流与重绘理解

回流:布局是页面首次加载时进行的操作,重新布局即为回流。

重绘:绘制是页面首次加载时进行的操作,重新绘制即为重绘。

什么时候会发生回流和重绘呢:

  • 当页面的某部分元素发生了尺寸、位置、隐藏发生了改变,页面进行回流。得对整个页面重新进行布局计算,将所有尺寸,位置受到影响的元素回流。
  • 当页面的某部分元素的外观发生了改变,但尺寸、位置、隐藏没有改变,页面进行重绘。(同样,只重绘部分元素,而不是整个页面重绘)

回流的同时往往会伴随着重绘,重绘不一定导致回流

那么具体什么操作会引起回流呢:

  • 页面初始化渲染
  • 窗口的尺寸变化
  • 元素的尺寸、位置、隐藏变化
  • DOM结构发生变化,如删除节点
  • 获取某些属性,引发回流
    • 很多浏览器会对回流进行优化,一定时间段后或数量达到阕值时,做一次批处理回流。
    • 当获取一些属性时,浏览器为了返回正确的值也会触发回流,导致浏览器优化无效,有:
      1. offset(top/bottom/left/right)
      2. client (top/bottom/left/right)
      3. scroll (top/bottom/left/right)
      4. getComputedStyle()
      5. width,height
    • 其次,字体大小修改及内容更新也会导致回流

 频繁的回流与重绘会导致频繁的页面渲染,导致cpu或gpu过量使用,使得页面卡顿。

那么如何减少回流呢:

  1. 减少逐项更改样式,最好一次性更改style,或是将更改的样式定义在class中并一次性更新
  2. 避免循环操作DOM,而是新建一个节点,在他上面应用所有DOM操作,然后再将他接入到DOM中
  3. 当要频繁得到如offset属性时,只读取一次然后赋值给变量,而不是每次都获取一次
  4. 将复杂的元素绝对定位或固定定位,使他脱离文档流,否则回流代价很高
  5. 使用硬件加速创建一个新的复合图层,当其需要回流时不会影响原始复合图层回流

浏览器页面的渲染流程

1. 解析html得到DOM树 

 2. 解析css得到CSS树 

 3. 合并得到render树 

 4. 布局,当页面有元素的尺寸、大小、隐藏有变化或增加、删除元素时,重新布局计算,并修改页面中所有受影响的部分 

 5. 绘制,当页面有元素的外观发生变化时,重新绘制 

 6. GUI线程将得到的各层的位图(每个元素对应一个普通图层)发送给Browser进程,由Browser进程将各层合并,渲染在页面上

css的堵塞情况

首先,是在Browser进程中下载css文件,当下载完成后,发送给GUI线程。

 其次,是在GUI线程中解析html及css,不过这两者是并行的。

 由于css的下载和解析不会影响DOM树,所以不会堵塞html文件的解析,但会堵塞页面渲染。

 这样的设计是非常合理的,如果css文件的下载和解析不会堵塞页面渲染,那么在页面渲染的途中或结束后发现元素样式有变化,则又需要回流和重绘。

js的堵塞情况

明确的是,js文件的下载和解析执行都会堵塞html文件的解析及页面渲染。

 因为js脚本可能会改变DOM结构,若是其不堵塞html文件的解析及页面渲染的话,那么当js脚本改变DOM结构或元素样式时,会引发回流和重绘,会造成不必要的性能浪费,不如等待js执行完,在进行html解析和页面渲染。

 如果你不想js堵塞的话,则使用async属性,这样就可以异步加载js文件,加载完成后立即执行。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值