垃圾回收(Garbage Collection,简称GC)是编程语言中提供的自动的内存管理机制,自动释放不需要的对象,让出存储器资源,无需程序员手动执行。
Golang中的垃圾回收主要应用三色标记法,GC过程和其他用户goroutine可并发运行,但需要一定时间的STW(stop the world),STW的过程中,CPU不执行用户代码,全部用于垃圾回收,这个过程的影响很大,Golang进行了多次的迭代优化来解决这个问题。
Go V1.3之前的标记-清除(mark and sweep)算法
此算法主要有两个主要的步骤:
- 标记(Mark phase)
- 清除(Sweep phase)
第一步,暂停程序业务逻辑, 找出不可达的对象,然后做上标记。第二步,回收标记好的对象。
操作非常简单,但是有一点需要额外注意:mark and sweep算法在执行的时候,需要程序暂停!即 STW(stop the world)。也就是说,这段时间程序会卡在哪儿。

第二步, 开始标记,程序找出它所有可达的对象,并做上标记。如下图所示:

第三步, 标记完了之后,然后开始清除未标记的对象. 结果如下.

第四步, 停止暂停,让程序继续跑。然后循环重复这个过程,直到process程序生命周期结束。
标记-清扫(mark and sweep)的缺点
- STW,stop the world;让程序暂停,程序出现卡顿 (重要问题)。
- 标记需要扫描整个heap
- 清除数据会产生heap碎片
所以Go V1.3版本之前就是以上来实施的, 流程是

Go V1.3 做了简单的优化,将STW提前, 减少STW暂停的时间范围.如下所示

这里面最重要的问题就是:mark-and-sweep 算法会暂停整个程序 。
Go是如何面对并这个问题的呢?接下来G V1.5版本 就用三色并发标记法来优化这个问题.
Go V1.5的三色并发标记法
三色标记法 实际上就是通过三个阶段的标记来确定清楚的对象都有哪些. 我们来看一下具体的过程.
第一步 , 就是只要是新创建的对象,默认的颜色都是标记为“白色”.

这里面需要注意的是, 所谓“程序”, 则是一些对象的跟节点集合.

所以上图,可以转换如下的方式来表示.
第二步, 每次GC回收开始, 然后从根节点开始遍历所有对象,把遍历到的对象从白色集合放入“灰色”集合。

第三步, 遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合

第四步, 重复第三步, 直到灰色中无任何对象.


第五步: 回收所有的白色标记表的对象. 也就是回收垃圾.

以上便是三色并发标记法, 不难看出,我们上面已经清楚的体现三色的特性, 那么又是如何实现并行的呢?
Go是如何解决标记-清除(mark and sweep)算法中的卡顿(stw,stop the world)问题的呢?

最低0.47元/天 解锁文章
4745

被折叠的 条评论
为什么被折叠?



