本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
Golang作为高级语言它内部会自行的GC(垃圾回收)。如果我们能够更好的了解GC的策略,这对于我们开发过程中对于内存的合理使用是非常有帮助的,我们在不同的版本提供了不同的GC算法:
1.3之前:标记清除算法(mark and sweep)
1.5: 三色标记算法
1.8: 三色标记+混合写屏障
今天这篇文章我们一起来探讨这三种不同的GC算法以及他们的优缺点
标记清除算法
-
标记
如上图所示,当程序开始GC时会先标记可达对象(也就是有引用指向的对象)。经过标记后图中的红色对象保留
-
清除 经过上一轮的标记后,我们发现对象5是没有引用指向的,所以对象5会在这一轮GC中被清除
缺点:
- 会产生STW 标记清除算法有个问题时,在整个标记清除阶段程序会进入STW(Stop the World)。STW过程中,Golang调度器阻塞,也就是不会执行任何用户代码,整个应用程序阻塞。标记清除的STW如下如所示
2. 标记阶段需要扫描整个堆(性能较差)
3. 容易产生内存碎片
三色标记算法
三色标记发采用逻辑上的黑、灰和白三种颜色来标记对象。GC和用户协程可以异步执行,在一定程序上减少了STW的时间。
STEP1
如上图所示,三色标记法的第一步会将所有的对象都标记成白色
STEP2
第二步会遍历Root Set(Golang的对象管理集合)第一层(不会进行递归遍历),取到可达对象Object1,Object4。将这两个对象放入灰色标记表
STEP3
本次会扫描灰色表中的Object1,Object4对象,将这两对象的下一层可达对象放入灰色标记表中,然后将这两对象放入黑色标记表中。经过这一轮后,Object1、Object4被放入黑色标记表。Object2被放入灰色标记表
STEP4
重复STEP2和STEP3,将灰色表中的对象全部搬移至黑色标记表时,整个三色标记法结束。白色标记表中剩下的对象就是此次GC要清除的对象。
以上是整个三色标记法的流程,很明显在开始标记时STW就会开始,然后当确定白色标记表中的对象时,STW就会结束。到目前为止也没用看出三色标记法有多高效。
后续文章我们继续探讨,Golang为了提高GC效率所采用的强/弱三色标记算法,以及三色标记+混合写屏障