从Js到V8引擎:垃圾回收

垃圾回收常见的几个算法(机制)

  1. 引用计数
  2. 标记清除
  3. 标记清除整理
  4. Cheney算法:目前V8引擎新生代垃圾回收

我们来逐个讲解。


JS的垃圾回收机制

Js的垃圾回收机制主要分为两个:

  • 标记清除法
  • 引用计数法

前置概念:什么是循环引用:

循环引用非彼for循环。

循环引用指的是两个或多个对象之间相互引用对方,形成一个闭环的引用链。举例说,对象 A 引用了对象 B,而对象 B 也引用了对象 A,这样就形成了循环引用。

 

标记清除法

这是Js垃圾回收机制中最常用的一种算法。

  1. 阶段一: 标记阶段

    1. 垃圾回收器会从跟对象(可以理解为全局对象和当前执行上下文的局部变量?)开始,遍历所有。
    2. 在遍历的过程中,会先给所有对象来标记一个状态,假设 1 所示在使用。
  2. 阶段二:清除标记

    1. 垃圾回收器会检查一边所有的对象(遍历),如果发现某个对象没被标记为 1 而是 0 (没被使用)
    2. 它会把所有标记为 0 的对象删除,释放内存。

这种方法的优点是能够有效处理循环引用的问题,因为只要对象被标记为 0 ,就会被回收,不管在不在循环体中。

引用计数

引用计数是一种较为简单的垃圾回收策略,因为简单,所以天然但存在一些缺陷,对于一些循环引用的对象难以处理。

  1. 阶段一: 引用计数机制

    1. 每个对象都有一个引用计数器属性(在原型链上),这个属性记录有多少个其他对象在引用它。
    2. 当一个新引用指向该对象时,引用计数器加一;当一个引用被删除时,引用计数器减一。
  2. 阶段二:回收阶段

    1. 对于哪些引用计数为 0 的对象,js就会判定他为未被引用,然后删除它。

无论是标记清除还是引用计数法,都是原生的JS的垃圾回收机制。他们天然存在一些缺陷。

  • 引用计数法: 对循环引用无法处理。
  • 标记清除法:存在暂停时间长、内存碎片以及非实时性问题。

上面既然说了 原生Js 对于垃圾回收机制存在缺陷,那么这些问题要怎么解决?其实强大的 V8引擎 就提出了新的方法和管理模式来对内存进行更准确地管理

V8 引擎中的垃圾回收机制

V8 引擎是 Google 开发的高性能 JavaScript 和 WebAssembly 引擎,广泛应用于 Chrome 浏览器和 Node.js 中。为了提升垃圾回收的效率和减少对应用程序性能的影响,V8 引擎对 JavaScript 的垃圾回收机制进行了多种优化。

关于V8有很多的地方可以研究,我们就来探究它对于垃圾回收的优化。

分代垃圾回收

V8引擎把内存划分为两块(Chenney算法):新生代、老生代。

  1. 新生代

    1. 存放一些生命周期比较短的对象。
    2. 用了特殊的算法:通过复制收集机制,将还在存活的对象从一个空间复制到另外一个空间,没有被复制的对象(未使用的)就会被回收。
    3. 这个特殊的算法执行时间短,成本低,新生代对象存活时间比较短,回收频率高。
  2. 老生代

    1. 存放一些生命周期较长的对象。
    2. 使用标记-清除和标记-压缩算法。
    3. 标记-清除:遍历并标记活跃对象,然后清除未标记的对象。
    4. 标记-压缩:在清除阶段后进行内存整理,将存活对象压缩到内存的一端,以减少内存碎片。

很抽象,较难理解。。。

  1. 初始时,新生代空间存在1,2,3三个对象,占用空间大小我们用矩形面积来表示。这个时候新增变量 4,但是原先内存空间因为不连续,导致4放不下。

  1. 于是,复制算法作用下,将新生代和即将加入的 4 复制放入到 老生代空间,并用进行了重排。

  1. 复制收集完成后,(交换空间)将老生代和新生代互换,等下下次对象的变化。

以上只是新生代和老生代转变重排的示例,在接下来的循环中,新老生代中复制收集算法、标记清除算法同时生效。将不活跃的老生代清除掉,来释放空间。

V8在垃圾回收时用到的机制:

  1. 增量标记:将标记阶段分成多个小步骤,逐步完成标记过程。
  2. 并发标记: 在后台线程中执行标记操作,不阻塞主线程。
  3. 延迟清理: 在标记阶段完成后,并不立即进行全部清理操作。而是将清理操作分散到后续的内存分配过程中,这样可以平摊清理成本,避免一次性清理带来的性能开销。
  4. 并行 清理: 在多个线程中并行执行清理操作。
  5. 内存 压缩: 将存活对象移动到内存的另一端,释放出连续的大块内存空间。

Cheney算法

上面说到,V8把内存划分为两块,其实这其中用到了Chenney算法:一种高效的垃圾回收算法,属于复制收集(Copying Collection)技术的一种。

Cheney算法将内存分成两个半空间,分别称为“从空间”(From-space)和“到空间”(To-space)。

浅谈Cheney算法原理

  1. 初始化: 所有对象最初都分配在“从空间”中。

  2. 复制阶段:从根对象开始,遍历所有可达对象,将它们从“从空间”复制到“到空间”。

  3. 更新阶段: 在复制过程中,更新所有对象的引用,以确保它们指向“到空间”中的新对象。

  4. 交换空间: 完成复制后,交换“从空间”和“到空间”的角色,原来的“到空间”变为新的“从空间”,所有存活对象现在都在这个空间中,原来的“从空间”则可以完全清空。

  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44189802

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值