垃圾回收机制

垃圾回收(Garbage Collection,简称GC)是编程语言中提供的自动的内存管理机制,自动释放不需要的对象,让出存储器资源,无需程序员手动执行

参考

发展历程

标记-清除(mark and sweep)算法 - golang1.2

第一步,暂停程序业务逻辑, 找出不可达的对象,然后做上标记。第二步,回收标记好的对象。

即找到不可达对象,然后进行删除

缺点

  • STW,stop the world;让程序暂停,程序出现卡顿 (重要问题)。
  • 标记需要扫描整个heap
  • 清除数据会产生heap碎片

三色并发法 -go 1.5

步骤

  1. 首先将所有的对象都标记为 白色,表示为默认对象
  2. 从根节点的集合开始进行遍历,将可以遍历到的对象标记为 灰色
  3. 遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合
  4. 如果还存在又白色对象,那么就为垃圾,直接将其回收

但是当同时进行删除和插入的时候显然会出现刚刚删除的对象被引用,
(条件1: 一个白色对象被黑色对象引用(白色被挂在黑色下)

条件2: 灰色对象与它之间的可达关系的白色对象遭到破坏(灰色同时丢了该白色))


因此我们需要进行 STW(暂停程序),但是 STW 又会严重的影响性能,因此我们需要设计一个方法来减少stw带来的影响

stw方案的替代

强、弱三色不变式

强、弱三色不变式的目的是为了破坏 stw 丢失对象的两个条件

强三色不变式

强三色不变式:不存在黑色对象引用到白色对象的指针。

原理:通过破坏条件一防止对象进行丢失

弱三色不变式

弱三色不变式:所有被黑色对象引用的白色对象都处于灰色保护状态.

原理:假设条件一成立,通过破坏条件二实现防止丢失对象

插入屏障机制

在A对象引用B对象的时候,B对象被标记为灰色。(将B挂在A下游,B必须被标记为灰色)

但是我们知道,黑色对象的内存槽有两种位置, . 栈空间的特点是容量小,但是要求相应速度快,因为函数调用弹出频繁使用,
所以“插入屏障”机制,在栈空间的对象操作中不使用. 而仅仅使用在堆空间对象的操作中.

删除屏障机制

被删除的对象,如果自身为灰色或者白色,那么被标记为灰色。

但是这种方式的回收精度低,一个对象即使被删除了最后一个指向它的指针也依旧可以活过这一轮,在下一轮GC中被清理掉。

混合写屏障机制

由于对于栈空间的不适用,以及回收精度低等问题

规则

具体操作:

1、GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW),

2、GC期间,任何在栈上创建的新对象,均为黑色。

3、被删除的对象标记为灰色。

4、被添加的对象标记为灰色。

优点

Golang中的混合写屏障满足弱三色不变式,结合了删除写屏障和插入写屏障的优点,只需要在开始时并发扫描各个goroutine的栈,使其变黑并一直保持,这个过程不需要STW,而标记结束后,因为栈在扫描后始终是黑色的,也无需再进行re-scan操作了,减少了STW的时间。