GC算法是干什么的

GC算法介绍

  • GC定义
    • GC可以理解为就是垃圾回收机制的简写
    • GC可以帮找到内存中的垃圾,并释放和回收空间
      • GC里边垃圾是什么
        • 程序当中不再需要使用的对象 — 如果我们某一个数据,在使用完成之后上下文里边不再需要用到他了,我们就可以把它当作垃圾看待,例如name,当函数调用完成后,我们就不再需要使用name了,从需求的角度考虑,他应该是被当作垃圾然后被回收掉的,至于有没有被回收先不考虑
        function func() {
            name = 'xl'
            return `my name is ${name}`
        }
        func()
        
        • 程序中不能在访问到的对象 — 在函数调用结束之后,我们在外部的空间当中,就不能在访问到name,所以当我们找不到它的时候,其实它也可以算作是一种垃圾
        function func() {
            const name = 'xl'
            return `my name is ${name}`
        }
        func()
        
  • 什么是GC算法
    • GS是一种机制,垃圾回收器完成具体的回收工作
    • 工作的内容就是查找垃圾 / 释放空间 / 回收空间
    • 算法就是工作时查找和回收所遵循的规则
      1. 如何去查找空间
      2. 释放空间时应该如何释放
      3. 回收空间如何去进行分配
      4. 这些过程必然有不同的方式,这个GC的算法就可以理解为上述的垃圾回收器在工作过程中所遵循的一些规则
  • 常见GC算法
    • 引用计数
      • 通过一个数字来判断当前这个变量时是不是一个垃圾
    • 标记清除
      • 在GC工作的时候给那些活动的对象添加上一个标记,然后判断是不是一个垃圾
    • 标记整理
      • 与标记清除很类似,我们后续回收的过程中可以做一些不同的事情
    • 分代回收
      • 在V8中会用到

引用计数算法实现原理

  • 核心思想:在内部,通过一个引用计数器来维护当前对象的引用数,从而判断当前引用数是否为0来判断它是否是一个垃圾对象。当这个数值为0时,GC就开始工作,将其所在的对象空间回收和释放在使用
    • 引用计数器:相对于其他一些GC算法来说,也正是由于引用计数器的存在,导致了引用计数再执行效率上,可能有其他的算法有区别
  • 当某一个对象的引用关系改变时,引用计数器主动修改当前对象所对应的引用数值
  • 假设代码中现在有一个引用空间,目前来说有一个变量名指向它,这个时候我们就把数值加1,如果在说这个时候又多一个对象还是指向它,那么我们就把数值在加1,如果是减少的情况就减1,如果为0时,那么GC就会立即工作将当前的对象空间回收
const user1 = {age: 18}
const user2 = {age: 28}
const user3 = {age: 38}

const nameList = [user1.age, user2.age, user3.age]

function fn() {
    const num1 = 1
    const num2 = 2
}

fn()    // 不可以获取内部变量

function fn1() {
    num1 = 1
    num2 = 2
}

fn1()   // 可以获取到内部变量
  • 总结:其实就是靠着当前对象身上的一个引用计数的数值,来判断是否为0,从而决定它是不是一个垃圾对象

引用计数算法优缺点

优点

  • 发现垃圾时立即回收
    • 它可以根据当当前这个引用数是否为0来决定这个对象是不是一个垃圾,如果找到了,那就可以立即进行释放
  • 最大限度减少程序暂停
    • 我们的应用程序再执行的过程中,必然会对内存进行一个消耗,而我们当前的执行平台他的内存肯定会有上限的,所以内存肯定会有沾满的时候,不过由于引用计数算法他是时刻监控着那些引用数值为0的对象,所以我们就可以认为,当他发现这个内存即将饱满时,那么引用计数就会立马去找到那些数值为0的计算空间,然后对其进行释放,这样就保证了我们当前的一个内存是不会有占满的时候

缺点

  • 无法回收循环引用的对象
  • 时间开销大
    • 因为当前的引用计数它需要去维护一个数值的变化,所以在这个情况下,他要时刻的去监控着当对象的一个引用数值是否需要修改,本身来说,这个对象的数值修改就需要消耗时间,如果说这个内存里边有更多的对象需要修改,那么这个时间就会显得更大一些。
function fn() {
    const obj1 = {}
    const obj2 = {}

    obj1.name = obj2
    obj2.name = obj1
    
    return 'xl'
}

fn()
/**
 * 我们这个函数执行结束后,内部所在的空间,肯定会涉及到空间回收的情况
 * 
 * 比如说obj1 obj2 因为在全局的地方我们已经不在直接去指向他了
 * 
 * 所以这个是他的引用计数应该为0
 * 
 * 但是现在会有一个问题:
 * 
 * 在里边当我们想要去找GC来把obj1删除时,obj2现在有一个属性指向obj1
 * 
 * 换句话说,按照之前的规则,我们在全局作用域下,找不到obj1和obj2了
 * 
 * 但是由于他两者之间在同一作用域内明显还有互相指引的关系
 * 
 * 所以在这种指引下他们身上的引用计数器的数值还不为0
 * 
 * 这时引用计数算法下的GC就没有办法将其回收,从而造成了内存空间的浪费
 * 
 * 这就是所谓的对象之间的循环引用
 * */ 

标记清除算法实现原理

  • 相对于之前的引用计数算法,这个算法的原理实现更加简单,而且还能拿个解决一些相应的问题,在后续的V8当中会被大量的使用到
  • 核心思想:分标记和清除两个阶段完成
    • 遍历所有对象,找到活动对象,进行标记
      • 活动对象和可达对象是一个道理
    • 遍历所有对象,没有标记的对象进行清除
      • 注意:第二阶段会把第一阶段设置的标记抹除,便于GC下次还能正常工作
  • 通过两次遍历行为回收相应的空间,最终再交给相应的空闲列表进行维护,后续我们的程序代码可以实现使用

标记清除算法优缺点

  • 作为一个GC算法,它依然是做不到完美无瑕的

优点

  • 解决对象循环引用的回收操作

缺点

  • 回收完成之后地址不连续,后续我们想去申请一片空间,刚好申请的空间大小是1.5格子,这种情况下,有的回收空间是两个格子,有的是一个格子,这个时候造成了一个当前标记清除算法中最大的问题 — 空间的碎片化
    • 空间碎片化 ---- 由于我们当前所回收的垃圾对象,在地址上他本身是不连续的,由于这种不连续从而造成了,我们在回收之后他们分散在各个角落,后续我们想去使用时,新的生成空间刚好与他们大小匹配,那就可以直接使用,一旦是多了或者少了,就不太适合使用了,所以这就是我们标记清除算法当中的一个缺点

标记整理算法实现原理

  • 和标记清除算法一样,在V8当中经常会被使用到
  • 标记整理其实可以看作为标记清除的增强操作
    • 因为标记阶段的操作和标记清除是一样的,因为他们都是遍历所有对象,然后将当前的可达活动对象进行标记
  • 清除阶段时,标记清除算法是直接将未被标记的垃圾对象做空间的回收,但是标记整理会在清除之前,先执行一个整理的操作,移动对象的位置,去让他们能够在地址上产生一个连续

常见GC算法总结

  • 引用计数
    • 在内部去通过一个引用计数器来维护每个对象都存在的一个引用数值,通过这个数值是否为0来判断这个对象是否为垃圾对象,从而去回收他的一个垃圾空间
    • 优缺点
      • 可以即使回收垃圾对象
      • 减少程序卡顿时间
      • 无法回收循环引用的对象
      • 资源消耗较大
  • 标记清除
    • 标记 — 遍历所有对象,然后给当前活动对象标记
    • 清除 — 遍历所有对象,然后给没有被标记到的对象的空间回收
    • 优缺点
      • 可以回收循环引用的对象
      • 容易产生碎片化空间,浪费空间
      • 不能够立即回收垃圾对象
  • 标记整理
    • 标记 — 遍历所有对象,然后给当前活动对象标记
    • 清除 — 遍历所有对象,在清除之前,先执行一个整理的操作,移动对象的位置,去让他们能够在地址上产生一个连续,然后给没有被标记到的对象的空间回收
    • 优缺点
      • 减少碎片化空间
      • 不会立即回收垃圾对象
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值