from 从输入 URL 到页面加载的过程?如何由一道题完善自己的前端知识体系!
作为进阶回头再来看看:从输入 URL 到页面加载完成的过程中都发生了什么事情?
回收机制
JS 有垃圾处理器,所以无需手动回收内存,而是由垃圾处理器自动处理。
一般来说,垃圾处理器有自己的回收策略。
譬如对于那些执行完毕的函数,如果没有外部引用(被引用的话会形成闭包),则会回收。(当然一般会把回收动作切割到不同的时间段执行,防止影响性能)
常用的两种垃圾回收规则是:
- 标记清除
- 引用计数
js 引擎基础 GC 方案是(simple GC):mark and sweep(标记清除),简单解释如下:
- 遍历所有可访问的对象。
- 回收已不可访问的对象。
譬如:(出自 js 高程)
- 当变量进入环境时,例如,在函数中声明一个变量,就将这个变量标记为“进入环境”。
- 从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。
- 而当变量离开环境时,则将其标记为“离开环境”。
- 垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。
- 然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包,也就是说在环境中的以及相关引用的变量会被去除标记)。
- 而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。
- 最后,垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。
关于引用计数,简单点理解:
跟踪记录每个值被引用的次数,当一个值被引用时,次数+1,减持时-1,下次垃圾回收器会回收次数为 0 的值的内存(当然了,容易出循环引用的 bug)
GC 的缺陷
和其他语言一样,javascript 的 GC 策略也无法避免一个问题: GC 时,停止响应其他操作
这是为了安全考虑。
而 Javascript 的 GC 在 100ms 甚至以上
对一般的应用还好,但对于 JS 游戏,动画对连贯性要求比较高的应用,就麻烦了。
这就是引擎需要优化的点: 避免 GC 造成的长时间停止响应。
GC 优化策略
这里介绍常用到的:分代回收(Generation GC)
目的是通过区分“临时”与“持久”对象:
- 多回收“临时对象”区(young generation)
- 少回收“持久对象”区(tenured generation)
- 减少每次需遍历的对象,从而减少每次 GC 的耗时。
像 node v8 引擎就是采用的分代回收(和 java 一样,作者是 java 虚拟机作者。)