# 垃圾回收机制

# 可触及

javaScript 内存管理的关键概念是可触及(Reachability)。简单来说,“可触及”的值就是可访问的,可用的,他们被安全储存在内存。

1、以下是一些必定“可触及”的值,不管出于任何原因,都不能删除:

  • 当前函数的局部变量和参数。
  • 当前调用链中所有函数的局部变量和参数。
  • 全局变量。
  • 其他内部变量。

这些值都称为 root。

2、其他值是否可触及视乎它是否被 root 及其引用链引用。

假设有一个对象存在于局部变量,它的值引用了另一个对象,如果这个对象是可触及的,则它引用的对象也是可触及的。

JavaScript 引擎有一个垃圾回收后台进程,监控着所有对象,当对象不可触及时会将其删除。

# 内部算法

基础的垃圾回收算法被称为“标记-清除算法”("mark-and-sweep"):

  • 垃圾回收器获取并标记 root。
  • 然后访问并标记来自他们的所有引用。
  • 访问被标记的对象,标记他们的引用。所有被访问过的对象都会被记录,以后将不会重复访问同一对象。
  • ……直到只剩下未访问的引用。
  • 所有未被标记的对象都会被移除。

# 算法优化

JavaScript 引擎在不影响执行的情况下做了很多优化,使这个过程的垃圾回收效率更高:

  • 分代收集 -- 对象会被分为“新生代”和“老生代”。很多对象完成任务后很快就不再需要了,所以对于他们的清理可以很频繁。而在清理中留下的称为“老生代”一员。
  • 增量收集 -- 如果对象很多,很难一次标记完所有对象,这个过程甚至对程序执行产生了明显的延迟。所以引擎会尝试把这个操作分割成多份,每次执行一份。这样做要记录额外的数据,但是可以有效降低延迟对用户体验的影响。
  • 闲时收集 -- 垃圾回收器尽量只在 CPU 空闲时运行,减少对程序执行的影响。

# 总结

  • 垃圾回收自动进行,我们不能强制或阻止其进行。
  • 可触及的对象会被保留在内存中。
  • 被引用不一定是可触及的(从 root):相互引用的对象可能整块都是不可触及的。

参考

Last Updated: 2/11/2020, 3:29:56 PM