前端知识——V8垃圾回收机制

众所周知,垃圾回收这个问题在前端面试的时候经常被提及,经常的回答就是引用计数和标记清除两种,几乎也就很少再问下去,其实v8中还有许多垃圾回收优化算法可以跟面试官好好聊聊~

先看看最常见的两种

一、引用计数

通过为每个对象维护一个引用计数器来判断对象是否仍然被引用。当引用计数为零时,对象即可被回收。 简单理解就是通过计数器,引用了就+1,赋值为null就-1,计数为0就清除。但这样就会出现问题:引用计数算法容易造成循环引用。

举个例子:obj1中有个a对象指向obj2,obj2中也有个a对象指向obj1那么这俩个对象就因为互相循环引用而永远不会被清除,因为始终存在一个引用计数所以计数器不为0,那么这些对象将无法被正常回收,导致内存泄漏。

二、标记清除

标记清除算法的核心是可达性,从根结点(root object)遍历通过标记所有活动对象,然后清除未被标记的对象。标记清除算法可以解决循环引用问题,标记-清除算法需要遍历整个对象图,因此在大型程序中可能会产生延迟和停顿。

三、其它算法优化

JS引擎比较广泛的采用就是标记清除算法,当然V8引擎为了进行更好的优化也会结合一些其它算法

1.标记整理

和标记清除相似,但不同的是回收时会将保留的储存对象汇集搬运到连续的内存空间,从而整合空闲空间,避免内存碎片化

如下图,假设存在ABCD四个内存引用当B被释放后这个内存空间可能无法满足添加进新的对象的大小,于是就需要开辟新的空间,这就会造成内存中可能存在许多碎片。

2.分代收集

对象分为两组“新的”和“旧的”,新的很快被清理,长期存活的对象变得“老旧”,检查频次也会减少。

如下图,这就是v8垃圾回收中的内存图,可以看到上面New space 、Old space ,创建的内存空间一开始会在New space中的其中一个semi space(A)中分配,一次垃圾回收后没有被清除的内存将拷贝到另一个semi space(B)中,一开始A为from space B为to space,再次创建使用内存空间时将会在另一个semi space(B)中分配,此时B为from space A为to space,没有被清除的内存也会拷贝到另一个semi space(A)中,两次都没有被清除的内存空间会被标记为“Old”(老旧),将会被放在Old space中,而老空间将减少检查频次从而优化性能。

3.增量收集

对应解决标记清除的问题,将垃圾收集工作分为几部分来做,然后将这几部分逐一进行处理,这样会有许多微小的延迟而不是一个大的延迟

4.闲时收集

垃圾收集器只会在cpu空闲时尝试运行,以减少可能对代码执行的影响

这就是v8中垃圾回收机制采用的方式及其优化算法介绍,有了这些内容基本就可以和面试官好好聊聊了,如果想了解更多知识可以自行查阅v8的源码,可能会有更深的体会~。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值