为何需要垃圾回收
JS的垃圾回收系统会自动进行,为了让系统可以重复利用内存,避免内存暴增
V8引擎的内存限制
为了减少性能引起的影响,基于以下两点的原因,限制了V8引擎的内存大小。
node 可以手动设置。
• 因为JS单线程,垃圾回收会阻碍主线程逻辑 • 垃圾回收本身耗时
V8的内存结构
对象开始都会分配在**新生代(new_space)**中,该区域由两个半空间(semispace)构成。
一个处于激活状态的From空间,一个处于未激活的To空间。
当进行垃圾回收时,From中的空闲对象被自动回收,存活对象则被复制到To空间。
复制完成后,From变成To,To变成From。
这个过程用了 Scavenge算法。
当:
- 对象经历过一次 Scavenge算法
- To的内存空间超过了 25%
对象就会进入到老生代中,这个过程叫对象晋升。
在老生代中,采用新的算法Mark-Sweep(标记清除)和Mark-Compact(标记整理)来进行管理。
引用计数
有个已经被淘汰的算法叫引用计数,当没有对象饮用的时候,该对象就会被回收。
但当出现循环引用的时候,垃圾回收器无法正确清除对象引用,容易发生内存泄漏。
Mark-Sweep
Mark-Sweep会从根结点出发,遍历访问所有可以访问到的子节点,并将其标记为活动的,非活动的则直接清除。 根结点包括
• 全局对象 • 本地函数的局部变量和参数 • 当前嵌套调用链上的其他函数的变量和参数
Mark-Compact
经历过Mark-Sweep之后,因为清理的内存地址不是连续的,所以会出现内存碎片。
Mark-Compact 算法就是为了解决这种内存碎片。
它会将标记的活动对象都推到内存的一端,然后回收另一端的非活动对象。
弱引用
WeakSet 和 WeakMap 中的键名所引用的对象都是弱引用,在垃圾回收的工程中,不会将键名对该对象的引用考虑进去。 适合存储Dom节点。
参考:https://juejin.cn/post/6844904016325902344