Go GC
Go1.5 标记删除(Mark and Sweep)
原理
- 进入STW(Stop The World)阶段
- 遍历整个heap,排查未被引用的对象,并标记;
- 暂停STW
- 执行Sweep清除
缺点
- STW会让Go程序暂停,程序出现卡顿
- 标记需要扫描整个heap
- 清除数据会产生heap碎片
Go1.8 三色标记法 + 写入屏障
三色标记法
原理
- 维护三个标记表:
白色
,灰色
,黑色
- 程序初始时,所有对象标记为白色
- 从Root Set开发,每次只遍历一层,标记该层的对象为
灰色
(对象从白色
表中移到灰色
表) - 然后,以
灰色
标记表开始,遍历该表中的对象,将从这些对象开始的可达到对象(走一步),标记为灰色
,同时灰色
表中已经遍历过的对象,标记为黑色
(对象从灰色
表中移到黑色
表) - 循环上一步,继续遍历
灰色
表,直到灰色
表中无任何对象 - 剩下的白色即为需要删除的对象
上述过程,仍然需要STW,否则会出现并发导致的引用关系错乱,导致资源被错误的GC删除
写入屏障
原理
三色标记被破坏的情况有两种:
- 一个白色对象被黑色对象引用
- 灰色对象与它的可达白色对象关系遭到破坏(灰色同时丢失了该白色)
谷歌提出了两个三色不变色:
- 强三色不变性:强制性不允许黑色引用白色
- 弱三色不变性:黑色可以引用白色,但白色对像存在其它灰色(可非直接上级节点)引用该白色对象
只要三色不变色满足上述条件之一,即可解决三色标记必须使用STW问题
插入写屏障
插入屏障原理
- 对堆对象,在对象被引用时触发,A引用B时,B对象标记为
灰色
- 对栈对象,对象被引用时,不触发该过程以避免该标记过程对程序性能的影响;
- 此时在GC过程,遍历
灰色
表的过程,不需要STW,直到灰色
表为空结束 - 而此时栈上
黑色
对象可能引用白色
对象,为解决这个问题,需要在上一步灰色
表为空时,执行一些STW,并将栈上所有对象都标记为白色,并对这些对象重新执行一遍扫描;
缺点:在结束时,还需要额外扫描一次栈上的对象引用链,这会引入10-100ms;
删除屏障原理
- 被删除对象,如果自身为
灰色
或白色
,则会被标记为灰色
; - 该过程是满足弱三色不变式,保证
灰色
对象到白色
对象的路径不会断;
缺点:被删除对象,当前这一轮GC不会被删掉(因为会被转换成黑色),但会在下轮GC中删掉;
混合写屏障
原理
- GC开始时,扫描栈上的可达对象全部标记为
黑色
(期间不需要STW) - GC期间,任何在栈上创建的新对象,均为
黑色
- 被删除对象,被标记为
灰色
- 被添加的对象标记为
灰色
满足变形的弱三色不变色,混合了插入,删除写屏障的优点