V8垃圾回收机制

垃圾回收

垃圾回收分为手动回收和自动回收两种策略。js 需要垃圾回收吗?js 不像 java,c 对内存的管控可以自己来操作,不需要就可以通过 free 就释放即可。何时分配,何时销毁内存都是由代码来控制的。

如果创建了内存,而没有进行 free 回收。这种情况就被称为内存泄露。

js 中如何回收

js 的数据的存放是存储在栈和堆两种内存空间的。 自然,也就分为栈中的垃圾回收和堆中的垃圾回收。

栈中垃圾回收

function foo() {
    var name = '小明';
    function bar() {
        
    } 
    bar();
}

当执行到 bar 函数,就会创建 bar 函数的执行上下文,将 bar 压入到调用栈中。还有一个记录当前执行状态的指针(ESP),指向 bar 函数的执行上下文,表示当前正在执行 bar 函数。

bar 函数执行完,就要销毁 bar 函数的上下文,ESP就会下移到 foo 函数上下文,这个下移操作就是销毁 bar 函数执行上下文的过程。

只是做了下移动操作,等到下一次重新创建 bar 的上下文,就会将旧的上下文就行直接覆盖,也就可以销毁。

堆中的数据回收

即使栈中的数据被销毁了,但是堆中的对象仍然占用着空间。

要回收堆中的垃圾数据,需要使用 js 中的垃圾回收器。

垃圾回收的算法有很多种,但是没有哪一种能胜任所有的场景,需要权衡各种场景,根据对象的生存周期的不同而使用不同的算法,以达到最好的效果。

在 V8 中把堆分为新生代和老生代两个区域,新生代中存放的是生存时间短的对象,老生代中存放的是时间久的对象。

新生区通常只支持 1~8M的容量,老生区的容量就大很多了。 V8分别使用两个不同的垃圾回收器,以便高效地实施垃圾回收。

新生代的垃圾回收使用由 副垃圾回收器负责。

主垃圾回收器老负责老生代的垃圾回收。

垃圾回收流程。

  1. 标记空间中活动对象和非活动对象。

  2. 回收非活动对象所占据的内存。

  3. 内存整理。频繁回收,会导致内存出现大量不连续的空间。将不连续的内存空间称为内存碎片。 但是副垃圾回收器不会产生内存碎片。

副垃圾回收器

大多数小的对象都会被分配到新生区,使用比较频繁。

新生代中使用 Scavenge 算法。这个算法,会把新生代空间对半划分为两个区域,一半是对象区域,一半是空闲区域。

新加入的对象都会放到对象区域,当对象区域快被写满时,就需要执行一次垃圾清理操作。

在垃圾回收过程中,首先对对象区域的垃圾做标记;标记完,进入清理操作,副垃圾回收器会把这些存活的对象复制到空闲区域中,同时它还会把这些对象有序的排列起来。复制后空闲区域就没有内存碎片了。

完成复制后,对象区域与空闲区域进行角色翻转,完成了垃圾回收的操作,可以无限的将这块区域使用下去。

因为 Scavenge 算法,需要复制操作,为了执行效率,一般新生区都设置的娇小。

但是空间小,会导致很容易填充满。js 引擎采用了对象晋升策略。只要经过两次垃圾回收仍然存活的对象,就会被移动到老生区中。

主垃圾回收器

老生区的特点就是一是对象占用空间大,另一个是对象存活时间长。

主垃圾回收器采用 标记-清除的算法进行垃圾回收。

首先进行标记,标记是从一组根元素开始,递归的遍历这组根元素,在这个遍历过程中,能够到达的元素称为活动对象,没有到达的元素就是垃圾数据。

标记清楚算法后,会产生大量不连续的内存碎片。碎片过多导致大对象无法分配到足够的连续内存,产生了一种算法: 标记-整理。

它不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存。

全停顿

js 运行在主线程,一旦执行垃圾回收算法,都需要将正在执行的 js 脚本全部暂停下来,等待垃圾回收完毕后再恢复脚本执行。

这样主现场不能够做任何事情,就会造成卡顿。 新生代比较小,所以影响不大,但是老生代占用的空间大,全停顿的影响大。

为了降低老生代带来的影响, V8 将标记过程分为一个个子标记过程,同时让垃圾回收标记和 js 应用逻辑交替进行,直到标记阶段完成。这个算法就是 增量标记算法。

可以把一个完整的垃圾回收拆分为很多小的任务。可以穿插到其他 js 任务中间执行。这样带来的卡顿就比较小了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值