JS(13)详解js垃圾回收机制

1、JS的垃圾回收机制

  • 可达性,就是那些以某种方式可访问或者说可用的值,它们被保证存储在内存中,反之,如果不可访问则需要回收
  • JS的垃圾回收机制,简单点来说就是定期找出那些不再用到的内存(变量),然后释放内存
  • 关于垃圾回收机制,有两个最常见的算法策略:标记清除算法和引用计数算法

1.1、标记清除算法

  • 标记清除算法是JS中最常见的。它的清除算法过程大致如下:

    • 1)垃圾收集器在运行时会给内存中给所有的变量都加上一个标记,假设内存中所有的对象都是垃圾,将其全标记为0
    • 2)然后引起会从根对象上开始遍历,把不是垃圾的节点变为0
    • 3)清除所有标记为0的垃圾,销毁并回收它们所占用的内存空间
    • 4)最后,把所有内存中的对象标记都修改为0,等待下一轮垃圾回收

  • 优点:优点就是一个,实现起来比较简单,也无非打标记或者不打标记两种情况,这使得一位二进制(0或1)既可以为其标记,非常简单。

  • 缺点:它有一个很大的缺点,就是在清除之后,剩余对象内存位置是不变的,这就会导致空闲空间是不连续的,出现了内存碎片。正因为剩余的空间不是不是连续的,是分成很多由大小不同的内存组成的内存列表,这就会又牵扯出内存分配的问题。

  • 假设我们新建的对象,需要分配的内存大小为size,由于空闲的内存是间断的,不连续的,则需要对空闲内存列表进行一次单向遍历找出大于等于这个size的内存块才能为其分配。

  • 如何找到合适的内存块呢?

  • 最常用的一种方法是first-fit,即当找到大于等于size的内存块就立即返回,让这个新建对象分配到这个内存中

  • 归根结底,标记清除法的缺点在于清楚之后剩余的对象位置不变而导致的空闲内存不连续,解决这一问题是极为关键的。

  • 标记整理法:标记整理法可以有效地解决这个问题,它的标记阶段和清除阶段和标记清除算法没有什么不同,只是标记结束后,标记整理算法会将活着的对象向内存的一端移动,最后清除掉位于边界上的内存,这样就可以得到一整块的空闲内存了。

1.2、引用计数算法

  • 引用计数算法是最早先用到的一种垃圾回收算法。它把对象是否不再需要简化定义为对象有没有被其他对象所引用。如果没有引用指向该对象,对象就将被垃圾回收机制回收。

  • 它的算法策略是跟踪记录每个变量值被使用的次数,大致如下:

    • 1)当声明了一个变量并且将一个引用类型赋值给该变量的时候,这个值的引用次数就为1
    • 2)如果同一个值又被赋给另一个变量,那么引用数加1
    • 3)如果该变量的值又被其他的值覆盖了,则引用次数减1
    • 4)当这个值得引用次数为0的时候,说明没有变量在使用,这个值没法被访问。垃圾回收器会在运行时候清理掉引用次数为0的值所占用的内存。

  • 优点:清晰简单很多

  • 缺点:很大几个问题:

    • 首先它需要一个计数器,而此计数器需要占一个比较大的位置
    • 同时,它无法解决循环引用的问题。比如在一个函数作用域中,两个变量一直在相互引用,那么即使函数执行完毕,这两个变量也不会被清除,这样就会占据大量的无用的内存

2、v8引擎对GC的优化

  • 谷歌的v8引擎也是基于标记清除算法,但是它做了相应的优化过程
  • 试想一下,垃圾清除算法在每次垃圾回收时都要检查内存中所有的变量。
  • 但是对于一些比较大的,存活时间长的对象来说,它不需要进行频繁清理
  • 但是对于另外一些很小的,存活时间很短的,比较新的变量来说,却需要进行一个更频繁的清理。
  • 而V8的垃圾回收策略表示基于分代式垃圾回收机制
  • v8将堆内存中分为新生代和老生代两区域,并对此采用不同的垃圾回收策略

2.1、新生代垃圾回收

  • 新生代区域的对象都是存活时间较短的对象,通常只支持1~8M的容量
  • V8还将新生代区域一分为二,一个处于使用状态,为使用区,另一个为空闲状态,为空闲区
  • 新加入的对象都会被存放到使用区中,当使用区被快写满时,就执行一次垃圾清理操作
  • 当开始进行垃圾回收时,新生代垃圾回收器会对使用区的活动对象做标记,标记后复制一份活动对象到空闲区(这里做了排序,避免出现内存随便)
  • 然后清除使用区中的数据对象,把原来的使用区变为空闲区,再把原来的空闲区变为使用区。这样的话新的使用区就是空的,继续存放数据
  • 当存放快要满的时候再进行下一轮的垃圾回收,重复上面步骤
  • 这个时候假如发现了上次就存在的对象这次还是活动对象,那么这个对象就会被晋级,扔到老生代里面去。

2.2、老生代垃圾回收

  • 老生代的垃圾回收就是标记清除算法:
  • 首先是标记阶段,从一组根元素开始,递归遍历这组根元素,遍历过程中能达到的元素被称为活动对象,没有达到的元素可以判断为非活动对象
  • 清除阶段老生代垃圾回收器会直接将非活动对象,也就是数据清理掉。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值