GC算法介绍
- GC定义
- GC可以理解为就是垃圾回收机制的简写
- GC可以帮找到内存中的垃圾,并释放和回收空间
- 什么是GC算法
- GS是一种机制,垃圾回收器完成具体的回收工作
- 工作的内容就是查找垃圾 / 释放空间 / 回收空间
- 算法就是工作时查找和回收所遵循的规则
- 如何去查找空间
- 释放空间时应该如何释放
- 回收空间如何去进行分配
- 这些过程必然有不同的方式,这个GC的算法就可以理解为上述的垃圾回收器在工作过程中所遵循的一些规则
- 常见GC算法
- 引用计数
- 标记清除
- 在GC工作的时候给那些活动的对象添加上一个标记,然后判断是不是一个垃圾
- 标记整理
- 与标记清除很类似,我们后续回收的过程中可以做一些不同的事情
- 分代回收
引用计数算法实现原理
- 核心思想:在内部,通过一个引用计数器来维护当前对象的引用数,从而判断当前引用数是否为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()
标记清除算法实现原理
- 相对于之前的引用计数算法,这个算法的原理实现更加简单,而且还能拿个解决一些相应的问题,在后续的V8当中会被大量的使用到
- 核心思想:分标记和清除两个阶段完成
- 遍历所有对象,找到活动对象,进行标记
- 遍历所有对象,没有标记的对象进行清除
- 注意:第二阶段会把第一阶段设置的标记抹除,便于GC下次还能正常工作
- 通过两次遍历行为回收相应的空间,最终再交给相应的空闲列表进行维护,后续我们的程序代码可以实现使用
标记清除算法优缺点
优点
缺点
- 回收完成之后地址不连续,后续我们想去申请一片空间,刚好申请的空间大小是1.5格子,这种情况下,有的回收空间是两个格子,有的是一个格子,这个时候造成了一个当前标记清除算法中最大的问题 — 空间的碎片化
- 空间碎片化 ---- 由于我们当前所回收的垃圾对象,在地址上他本身是不连续的,由于这种不连续从而造成了,我们在回收之后他们分散在各个角落,后续我们想去使用时,新的生成空间刚好与他们大小匹配,那就可以直接使用,一旦是多了或者少了,就不太适合使用了,所以这就是我们标记清除算法当中的一个缺点
标记整理算法实现原理
- 和标记清除算法一样,在V8当中经常会被使用到
- 标记整理其实可以看作为标记清除的增强操作
- 因为标记阶段的操作和标记清除是一样的,因为他们都是遍历所有对象,然后将当前的可达活动对象进行标记
- 清除阶段时,标记清除算法是直接将未被标记的垃圾对象做空间的回收,但是标记整理会在清除之前,先执行一个整理的操作,移动对象的位置,去让他们能够在地址上产生一个连续
常见GC算法总结
- 引用计数
- 在内部去通过一个引用计数器来维护每个对象都存在的一个引用数值,通过这个数值是否为0来判断这个对象是否为垃圾对象,从而去回收他的一个垃圾空间
- 优缺点
- 可以即使回收垃圾对象
- 减少程序卡顿时间
- 无法回收循环引用的对象
- 资源消耗较大
- 标记清除
- 标记 — 遍历所有对象,然后给当前活动对象标记
- 清除 — 遍历所有对象,然后给没有被标记到的对象的空间回收
- 优缺点
- 可以回收循环引用的对象
- 容易产生碎片化空间,浪费空间
- 不能够立即回收垃圾对象
- 标记整理
- 标记 — 遍历所有对象,然后给当前活动对象标记
- 清除 — 遍历所有对象,在清除之前,先执行一个整理的操作,移动对象的位置,去让他们能够在地址上产生一个连续,然后给没有被标记到的对象的空间回收
- 优缺点