Go version1.3,标记清除法(Mark And Sweep)
步骤:
- 进行STW(stop the world,暂停程序的业务逻辑),找出不可达的对象和可达的对象
- 开始标记,程序找出可达内存占用并做标记
- 清楚未标记的对象,因为未标记的都是不可达的对象
- 结束STW,程序的业务逻辑继续运行。
- 整个程序的生命周期内循环执行上述步骤
优化:
互换第3步与第4步执行顺序,缩小STW影响范围(缩短程序逻辑暂停时间),清楚垃圾动作与程序逻辑并发执行
缺点:
1. STW(stop the world),让程序暂停,程序出现卡顿,性能影响很大(最大的问题)。
2.标记需要扫描堆栈信息
3.清除数据会产生heap碎片
Go version1.5,三色标记法
三色标记:
白色标记:未被识别引用的对象
灰色标记:临时状态,被识别到引用,但对象自身引用到其他的对象未被识别
黑色标记表:被识别后被引用的对象,对象自身所引用的对象也已被识别
步骤:
- 将所有对象标记为白色
- 从GC Roots(根节点集合)出发遍历所有对象,把遍历到的对象标记成灰色
- 遍历灰色集合,将当前灰色对象引用的对象标记为灰色,并把当前灰色对象标记为黑色
- 循环2,3步骤,直到没有灰色标记的对象
- 回收白色标记对象
优化:
强三色不变式:不允许黑色对象引用白色对象
弱三色不变式:黑色对象可以引用白色,白色对象存在其他灰色对象对他的引用,或者他的链路上存在灰色对象
屏障机制
插入屏障:对象被引用时触发的机制,当白色对象被黑色对象引用时,白色对象被标记为灰色(栈上对象无插入屏障,栈上的内存会在GC结束后启用STW重新扫描,大约需要10~100ms)。
删除屏障:对象被删除时触发的机制。如果灰色对象引用的白色对象被删除时,那么白色对象会被标记为灰色。这种做法回收精度较低,一个对象即使被删除仍可以活过这一轮再下一轮被回收。
Go version1.8,三色标记+混合写屏障
三色标记法节后插入屏障与删除屏障的特点,且整个GC过程不需要STW
具体操作:
- GC开始时将栈上可达对象全部标记为黑色(不需要二次扫描,无需STW)
- GC期间,任何栈上创建的新对象均为黑色
- 被删除引用的对象标记为灰色
- 被添加引用的对象标记为灰色
GC触发:
- 堆内存的分配达到控制器计算的触发堆大小,初始大小环境变量GOGC,之后堆内存达到上一次垃圾收集的 2 倍时才会触发GC。
- 如果一定时间内没有触发,就会触发新的循环,该触发条件由
runtime.forcegcperiod
变量控制,默认为 2 分钟。