浏览器的几种垃圾回收方法

106 阅读4分钟

1.引用计数法

其思路是对每个值都记录它被 引用的次数。声明变量并给它赋一个引用值时,这个值的引用数为 1。如果同一个值又被赋给另一个变

量,那么引用数加 1。类似地,如果保存对该值引用的变量被其他值给覆盖了,那么引用数减 1。当一 个值的引用数为 0 时,就说明没办法再访问到这个值了,因此可以安全地收回其内存了。垃圾回收程序 下次运行的时候就会释放引用数为 0 的值的内存。

优点

  • 可以即时回收垃圾对象
  • 减少程序卡顿时间

缺点

  • 无法回收循环引用的对象
  • 资源消耗比较大(因为需要维护对象的引用的数字会带来频繁的操作所以带来的资源消耗也会比较大)

什么是循环引用对象

var a={"name":"zzz"};
var b={"name":"vvv"};
a.child=b;
b.parent=a;

当出现循环引用即使变量后续已经不再使用 ,但由于循环引用的关系变量的被引用数字无法清零也就导致无法被引用计数法给清除掉。

2.标记清除法

javaScript 最常用的垃圾回收策略是标记清除(mark-and-sweep)。当变量进入上下文,比如在函数

内部声明一个变量时,这个变量会被加上存在于上下文中的标记。而在上下文中的变量,逻辑上讲,永

远不应该释放它们的内存,因为只要上下文中的代码在运行,就有可能用到它们。当变量离开上下文时,

也会被加上离开上下文的标记。

给变量加标记的方式有很多种。比如,当变量进入上下文时,反转某一位;或者可以维护“在上下

文中”和“不在上下文中”两个变量列表,可以把变量从一个列表转移到另一个列表。标记过程的实现

并不重要,关键是策略。

垃圾回收程序运行的时候,会标记内存中存储的所有变量(记住,标记方法有很多种)。然后,它

会将所有在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉。在此之后再被加上标记

的变量就是待删除的了,原因是任何在上下文中的变量都访问不到它们了。随后垃圾回收程序做一次内

存清理,销毁带标记的所有值并收回它们的内存。

优点

  • 相对引用计数法标记清除法可以清除循环引用对象

缺点

  • 容易产生碎片化空间
  • 不会立即回收垃圾对象

3.标记整理

该算法分为标记和整理两个阶段,标记阶段会遍历并标记活动对象,整理阶段通过数次搜索堆来重新装填活动对象,它们聚集到了堆的一端。 可以理解为在标记清除的基础上加了一项整理操作 将空闲出的碎片化空间合并到一起,提高空间利用效率。

优点

  • 相对标记清除不会产生碎片化空间

缺点

  • 和标记清除一样不会立即回收垃圾对象

4.v8引擎的新老生代算法

v8引擎会将浏览器的存储空间一分为二分别为新生代空间和老生代空间

新生代存储空间

新生代存储空间也会被一分为二 分为 From 和 To 。其中From空间为使用空间 To为空闲空间。当From空间使用即将占满时会对该空间进行 标记整理 操作然后再将该空间拷贝至To空间 。然后将From空间与To空间进行交换进行空间释放。

此时如果有变量在经历了一轮垃圾回收后依然存在那么就会将该变量晋升至老生代存储空间。

老生代存储空间

老生代存储空间主要采用标记清除加上标记整理来进行垃圾回收

V8并行回收

JavaScript是单线程语言 进行垃圾回收会阻塞脚本的执行 v8会采用并行的方法对js进行垃圾回收保证程序的正常执行不被阻塞

image-20221023175034782.png


以上只是个人在代码学习中的一些心得体会和笔记分享 如有错误还望大家能够指出批评