JS垃圾回收机制(V8)

最近在看JS的垃圾回收机制(原文链接: https://juejin.cn/post/6981588276356317214#heading-8),做个记录总结方便以后翻看

  1. 垃圾的产生
    我们创建的数据(对象、基本数据类型、函数等)都会在内存中占用对应的空间,当我们不需要使用这些数据的时候,它们就变成了垃圾。

  2. 垃圾回收
    上面说道我们不需要使用数据的时候它们就变成了垃圾,我们如何知道哪些数据不需要使用呢?
    比较流行的有两种方案:
    1)可达性分析(标记清除)
    每过一段时间从根对象出发,依次找到有依赖关系的对象,并做标记,表示这些对象在使用中,剩余未被标记的则表示没有在使用,进行清除
    优点:标记简单(可以使用1个2进制位标记,额外内存开销少)
    缺点:内存碎片化,每隔一段时间进行全量的扫描、清理,导致主线程卡死

    2)引用计数
    引用计数用来表示有多少指针指向当前内存空间,每当有一个变量引用当前内存空间时,引用计数就+1,反之则引用计数-1,当引用计数为0时,进行清理;
    优点:回收及时,引用计数为0时,立即回收
    缺点:1、循环引用 let a = {}; let b = {}; a.b = b; b.a = a; 2、引用计数也要占用内存空间,增加内存开销

  3. JS的垃圾回收
    JS通过可达性分析,标记出需要回收的内存,然后通过标记整理算法解决内存碎片化问题
    标记整理:在标记清除的基础上,标记完成后把正在使用中的内存移到内存空间的一侧,然后清理剩余的内存空间

  4. V8的优化
    1)分代式垃圾回收:
    有些存在比较久的(已经存在很久的内存空间,一般来说后续会存在更久),或者比较大的内存空间(个人感觉属于空间换时间)频繁的操作会比较浪时间,所以可以把内存分为两部分(新生代和老年代),新生代的扫描频率高于老年代的频率;
    1、新生代:又被分为两部分,一部分放使用区,另一部分是空闲区;新创建的对象放到使用区,每隔一段时间扫描使用区,把使用中的内存数据复制到空闲区,如果一个数据占用的内存大于某个值或者经过了多次复制依然存在或则空闲区的占用过大,则复制当前数据到老年代;当使用区的值整理完后,把空闲区标记为使用区并把之前的使用区清空标记为空闲区;
    2、老年代:使用标记清除和标记整理来处理
    2)并行回收
    由于标记清除期间,js是无法执行的(全停顿),如果清理时间过长会影响用户体验,如果能开辟多个线程同时回收则能在一定程度上重复利用系统资源,缩短清理时间;新生代就是利用并行回收优化性能
    3)增量标记
    对于老年代中内存占用大的数据,回收起来比较耗时,我们可以将垃圾回收分步进行,提升用户体验,老年代一次垃圾回收需要1s,如果一次性回收用户会有明显的感知,如果分为10步,则用户感知会大大降低
    1、如何保存和恢复上一次的回收环境:
    3色标记法:未被标记为白色;本身被标记,成员变量未被标记的记录为灰色;本身和成员变量都被标记的记录为黑色;
    把灰色的放入到一个标记工作表中,则下一次就可以恢复到之前的标记状态,继续标记
    2、标记为黑色的对象被改为了被改为了白色(黑色对象引用白色对象),则立马置为灰色(写屏蔽)
    4)懒性清理:如果内存充足,则可以延迟清理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值