ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
### 回收机制 JS有垃圾处理器,所以无需手动回收内存,而是由垃圾处理器自动处理。 一般来说,垃圾处理器有自己的回收策略。 譬如对于那些执行完毕的函数,如果没有外部引用(被引用的话会形成闭包),则会回收。(当然一般会把回收动作切割到不同的时间段执行,防止影响性能) 常用的两种垃圾回收规则是: - 标记清除 - 引用计数 Javascript 引擎基础GC方案是(`simple GC`):`mark and sweep`(标记清除),简单解释如下: 1. 遍历所有可访问的对象。 2. 回收已不可访问的对象。 譬如:(出自 javascript 高程) > 当变量进入环境时,例如,在函数中声明一个变量,就将这个变量标记为“进入环境”。 > > 从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。 > > 而当变量离开环境时,则将其标记为“离开环境”。 > > 垃圾回收器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。 > > 然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包,也就是说在环境中的以及相关引用的变量会被去除标记)。 > > 而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。 > > 最后,垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。 关于引用计数,简单点理解: **跟踪记录每个值被引用的次数,当一个值被引用时,次数 +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 虚拟机作者。) 更多可以参考:[V8 内存浅析](https://zhuanlan.zhihu.com/p/33816534)