乐趣区

关于gc:GC-垃圾回收机制认识与算法详解

目录

  • GC 相干概念
  • 常见 GC 算法
  • 援用计数算法

    • 核心思想
    • 实现原理
    • 实例
    • 优缺点
  • 标记革除算法

    • 核心思想
    • 实现原理
    • 图示
    • 优缺点
  • 标记整顿算法

    • 核心思想
    • 实现原理
    • 图示
    • 优缺点

GC 相干概念

  • [x] GC:垃圾回收机制的简写,垃圾回收期实现具体的工作. 能够找到内存中的垃圾、并开释和回收空间
  • [x] GC 垃圾:程序中 不再须要应用的 程序中不能再拜访的 对象
  • [x] GC 算法:是 GC 工作时查找和回收所遵循的规定

常见 GC 算法

  • 援用计数
  • 标记革除
  • 标记整顿
  • 分待回收(V8 用到的)

援用计数算法

核心思想

设置援用数,判断以后援用数是否为 0 来决定是不是垃圾对象,如果是 0GC就进行工作,进行回收。

实现原理

  • 援用计数器
  • 援用关系扭转时批改援用数字
  • 援用数字为 0 时立刻回收

实例

const user1 = {age: 11}
const user2 = {age: 12}
const user3 = {age: 13}
const nameList = [user1.age, user2.age, user3.age]

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

fn()

当函数调用过后,num1num2 在内部不能应用,援用数为 0,会被回收 ;
num3 是挂载在 window 上的,所以不会被回收 ;
下面的 user1user2user3nameList援用,所以援用数不为 0 不会被回收 ;

优缺点

援用计数算法 内容
长处 1. 发现垃圾时立刻回收 <br/>2. 最大限度缩小程序暂停,让空间不会有被占满的时候
毛病 1. 无奈回收循环援用的对象 <br/>2. 资源耗费开销大(对所有对象进行数值的监控和批改,自身就会占用工夫和资源)

上面举一栗子阐明下面毛病中无奈回收循环利用对象的状况:


function fn() {const obj1 = {}
  const obj2 = {}
  obj1.name = obj2
  obj2.name = obj1
  return 'hello world'
}

fn()
// obj1 和 obj2,因为相互有援用,所以计数器并不为 0,fn 调用之后仍旧无奈回收这两个对象

标记革除算法

相比原理实现更加简略,还能解决相应问题,V8当中会大量应用到。

核心思想

标记 革除 两个阶段实现

实现原理

  • 第一阶段:遍历所有对象找流动对象(可达对象)标记(档次用递归进行操作)
  • 第二阶段:遍历多有对象 革除 没有标记对象并抹掉第一个阶段标的标记
  • 回收相应空间,将回收的空间加到 闲暇链表 中,不便前面的程序申请空间应用

图示

优缺点

标记革除算法 内容
长处 绝对于援用计数算法来说解决对象循环援用的问题,部分作用域外面的内容无奈被标记,所以即便有援用还是会被革除掉
毛病 1. 空间链表地址不间断(空间碎片化),不能进行空间最大化应用 <br/>2. 不会立刻回收垃圾对象,革除的时候程序是进行工作的。

上面是空间链表地址不间断的图示,能够更好的帮咱们了解:

右边开释了 2 个字的空间,后边开释了 1 个字的空间,尽管看起来是开释了 3 个字的空间,然而地址是不间断的。如果要申请一个 1.5 字的空间,应用右边空间节约了0.5,时候左边又不够,会造成无奈最大化应用。

标记整顿算法

这个算法和标记革除算法配合在 V8 中也是广泛应用。

核心思想

标记 革除 两头,增加了内存空间的 整顿

实现原理

  • 标记整顿能够看做是标记革除的 加强
  • 标记阶段:与标记革除统一
  • 整顿阶段:革除钱先执行整顿,挪动对象地位,在地址上产生间断
  • 革除阶段:与标记革除统一

图示

开始会有很多流动对象和非流动对象,还有一些闲暇空间,回收前先开始整顿

整顿之后要将非流动对象进行革除

最初就留出了整个的闲暇空间

优缺点

标记整顿算法 内容
长处 相较标记革除算法缩小了碎片化空间
毛病 不会立刻回收垃圾对象,革除的时候程序是进行工作的。
退出移动版