概述

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

Golang的GC

Golang的GC版本变化:
1、标记清除: v1.3
2、三色标记: v1.5
3、混合写屏障+三色标记: v1.8

一、标记清除

在这里插入图片描述步骤
stw 暂停程序
mark: 标记可达对象(分类出可对象和不可达对象)
sweep: 清除不可达对象
stw 结束

怎么 mark 标记可达对对象?
答:从程序的根节点往下面访问, 能遍历到的就是可达对象, 遍历不到的就是不可达的对象
在这里插入图片描述
标记清除的缺点
1、存在STW。因为在GC阶段需要暂停整个程序,程序出现卡顿,严重影响性能(最重要的 )
2、标记过程需要扫描整个heap和stack(堆栈信息),无疑是加长了整个STW的持续时间,还是影响性能的问题
3、清除数据会产生heap碎片,也就是产生一些不连续的碎片内存空间,对后续的重用,重组增加了困难

标记清除算法的优化

标记清除算法整个 GC 都是在 STW, STW 的时间过长了

为了减少 STW 的时间, golang 将 STW 的范围缩小

在这里插入图片描述
但是整个的 STW 还是挺长的, 特别是当需要 mark 标记的对象越多, 需要 STW 的时间越多

于是 go 1.5 就用三色标记法来动态的滚动式的做 gc 将一次长的 stw 分散到多次短暂 stw 中去

二、三色标记

步骤
1、遍历根对象的第一层可达对象标记为灰色, 不可达默认白色
2、将灰色对象的下一层可达对象标记为灰色, 自身标记为黑色
3、多次重复步骤2, 直到灰色对象为0, 只剩下白色对象和黑色对象
4、sweep 白色对象

步骤一:遍历根对象的第一层可达对象标记为灰色, 不可达默认白色
在这里插入图片描述步骤二:将灰色对象 A 的下一层可达对象标记为灰色, 自身标记为黑色
在这里插入图片描述
步骤三:继续遍历灰色对象的下层对象,重复步骤2
在这里插入图片描述在这里插入图片描述步骤四:灰色对象为0, 清理白色对象

三色标记对象丢失
如果 gc 期间不 stw(暂停程序) 的话有可能对象丢失

一个黑色对象在 gc 期间链接了白色对象, 白色对象又没有任何的灰色对象可达就会导致对象的丢失

在这里插入图片描述上图刚刚标记完, 准备清除(此时程序并发执行 E 对象链接了B对象)

三色标记对象丢失解决方法

三色标记+混合写屏障就能解决这个问题

三、三色标记 + 混合写屏障

步骤

1、STW 扫描栈, 将可达对象标记为黑色
(混合写屏障也是要STW的, 网上很多文章都没说, scan stack 的时候要 STW,只是混合写屏障去掉了 rescan stack 这个步骤,时间在 1ms 左右)

2、gc 期间 stack 创建的对象都是灰色

3、gc 期间在堆添加混合写屏障
(链接/删除链接 元素都标记为灰色,屏障会略微减少程序性能, 因为会加一层)

在这里插入图片描述(1)上图刚刚标记完, 准备清除(此时程序并发执行 E 对象链接了B对象)

链接对象会经过混合写屏障, 新插入的元素会标记为灰色

(2)接下来按照三色标记继续遍历即可

更详细请参考:链接