Go内存原理(五)-GC原理

2,222 阅读5分钟

Go内存原理(五)-GC原理


前几章我们学习了Golang内存管理的基本原理(还不清楚内存管理的童鞋请移步看内存管理系列)。现在我们来看GC的基本原理是什么?

一、GC

GC(Garbage Collection)提供自动内存管理机制,自动释放回收不使用的内存对象,防止内存泄漏

GC的算法随着go语言版本的更新而不断变化

goV1.3之前标记-清除(mark and sweep)算法

goV1.5三色标记法

goV1.8三色标记法+混合写屏障法

我们将对以上算法进行原理剖析

触发GC的条件:

​ 1)主动触发,用户代码中调用 runtime.GC 会主动触发 GC ​ 2)默认每 2min 未产生 GC 时,golang 的守护协程 sysmon 会强制触发 GC ​ 3)当 go 程序分配的内存增长超过阈值时,会触发 GC

二、标记-清除(mark-and-sweep)(v1.3)

1、介绍

从名字看就会有2个步骤,标记和清除

​ 1) 暂停程序运行(STW) 对可达的对象进行标记 ​ 2) 清除未标记的对象 ​ 3)停止暂停,程序继续

引入STW(stop the world)是为了防止在标记过程中又发生了对象的引用,导致清除了正在使用的对象

2、优缺点

1)优点:简单 2)缺点:STW暂停程序,程序出现卡顿;标记需要扫描整个heap; 清除数据会产生碎片

三、三色标记(v1.5)

1、介绍

在标记-清除方法上增加了中间状态:黑色-灰色-白色 以减少STW的时间

黑色:已标记的对象,表示对象是跟对象的可达的

灰色:被黑色引用的对象,灰色为标记过程的中间状态,当灰色对象全部标记为黑色表示标记阶段全部完成

白色:未标记对象,在开始扫描时全部对象均为白色,若扫描完成后该节点还是白色,说明该对象不可达,在清除阶段会被清除

最后,只有2中颜色,白色被清除,黑色被保留

过程

1)开始时所有对象为白色 2)将所有根对象标记为灰色,放入队列 3)遍历灰色对象,将其标记为黑色,并将他们引用的对象标记为灰色,放入队列 4)重复步骤 3 持续遍历灰色对象,直至队列为空 5)此时只剩下黑色对象和白色对象,白色对象即为下一步需要清除的对象

根对象指的是运行当前时刻的栈以及全局数据区域

在三色标记中,减少了STW的时间。我们知道在三色标记中,增加了中间状态-灰色状态,这可以允许标记与用户代码并行执行,这里是怎么做到的呢,是因为三色标记加入了写屏障机制

写屏障机制:黑色对象的内存槽有两种位置, 栈和堆. 栈空间的特点是容量小,但是要求相应速度快,因为函数调用弹出频繁使用, 所以“写屏障”机制,在栈空间的对象操作中不使用. 而仅仅使用在堆空间对象的操作中。写屏障简单来说也就是对于已标记的黑色对象(堆)由于并发特性添加了新对象(白色),此时会触发写屏障,也就是会将添加的新对象标记为灰色,继续进行标记,最后标记完成后,刚刚标记的灰色也会变为黑色。这是对于堆而言。

若对于栈中已标记的黑色对象由于并发特性添加了新对象(白色)。在所有的标记完成之后,可能对于栈上还会存在白色对象被引用的情况,这个时候需要STW重新扫描栈,标记栈上引用的白色对象为灰色,继续扫描标记为黑色。这次STW大约的时间在10~100ms间

2、优缺点
  1. 优点:减少STW的时间
  2. 缺点:结束时需要STW来重新扫描栈,标记栈上引用的白色对象的存活

四、三色标记+混合写屏障法(v1.8)

1、介绍

避免了对栈重新扫描的过程,极大的减少了STW的时间。当然屏障技术的使用还是在堆上,要保证栈上的运行效率

​ 1)GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW) ​ 2)GC期间,任何在栈上创建的新对象,均为黑色 ​ 3)堆中被删除的对象标记为灰色(这里被删除是指的是删除引用关系) ​ 4)堆中被添加的对象标记为灰色(这里被添加是指的是添加引用关系)

可见混合屏障只需要在开始时并发扫描各个goroutine的栈,使其变黑并一直保持,这个过程不需要STW,而标记结束后,因为栈在扫描后始终是黑色的,也无需再进行re-scan操作了,减少了STW的时间

2、优缺点

几乎不需要STW的时间,效率更高

引用

第一篇文章适合初次接触GC的童鞋阅读

Golang三色标记、混合写屏障GC模式图文全分析

golang的gc原理

搞懂垃圾回收

下一篇。老规矩,学习GC的源码