js垃圾回收机制(GC)

一、垃圾回收策略

1.引用计数垃圾回收:

这是最初级的垃圾回收算法,此算法把“对象是否不在需要”简化定义为“有没有其他对象引用到它”。如果没有引用指向该对象,那么该对象会被垃圾回收机制回收。限制:无法回收循环引用。

2.标记-清除算法:

标记清除顾名思义是一种分两阶段对对象进行垃圾回收的算法。

第一阶段:标记。从根结点出发遍历对象,对访问过的对象打上标记,表示该对象可达。

第二阶段:清除。对那些没有标记的对象进行回收,这样使得不能利用的空间能够重新被利用。

这个算法假定设置一个叫做根(root)的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象并进行标记,把在上下文(全局作用域, 脚本作用域)中声明的变量,以及在全局被引用的变量的标记删除掉, 剩下的所有带标记的变量就被视为要删除的变量, 垃圾回收执行时释放它们占用的内存。(从根开始,垃圾回收器将找到所有可以获得的对象和回收所有不能获得的对象。)
这个算法比前一个要好,因为"有零引用的对象"总是不可获得的,但是相反却不一定,参考“循环引用"。
从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对"对象是否不再需要”的简化定义。

限制:1.那些无法从根对象查询到的对象都将被清除,尽管这是一个限制,但实践中我们很少会碰到类似的情况,所以开发者不太会去关心垃圾回收机制。

2.在清除垃圾之后,剩余对象的内存位置是不变的,就会导致空闲内存空间不连续。这样就出现了内存碎片,并且由于剩余空间不是整块,就需要内存分配的问题。(标记-整理算法可以解决)

二、V8中的垃圾回收机制

  • V8引擎的垃圾回收采用标记清除法与分代回收法
  • 分为新生代和老生代

针对不同对象采用不同算法:

(1)新生代:对象的存活时间较短。新生对象或只经过一次垃圾回收的对象。

(2)老生代:对象存活时间较长。经历过一次或多次垃圾回收的对象。

回收新生代对象

回收新生代对象主要采用复制算法(Scavenge 算法)加标记整理算法。而Scavenge 算法的具体实现,主要采用了Cheney算法。

对象晋升机制

一轮GC还存活的新生代需要晋升。

回收老生代对象

回收老生代对象主要采用标记清除、标记整理、增量标记算法,主要使用标记清除算法,只有在内存分配不足时,采用标记整理算法。

  • 首先使用标记清除完成垃圾空间的回收;
  • 采用标记整理进行空间优化;
  • 采用增量标记进行效率优化;
posted @ 2022-09-16 17:00  grigeorge  阅读(545)  评论(0)    收藏  举报