golang-GC垃圾回收

参考:https://juejin.cn/post/7040737998014513183#comment

垃圾回收(Garbage Collection,缩写为GC),是一种自动内存管理机制。

相关术语

赋值器:说白了就是你写的程序代码,在程序的执行过程中,可能会改变对象的引用关系,或者创建新的引用。

回收器:垃圾回收器的责任就是去干掉那些程序中不再被引用得对象

STW:全称是stop the word,GC期间某个阶段会停止所有的赋值器,中断你的程序逻辑,以确定引用关系。

root对象:根对象是指赋值器不需要通过其他对象就可以直接访问到的对象,通过Root对象, 可以追踪到其他存活的对象。常见的root对象有:栈变量、堆变量。

GC发展过程

v1.3 标记清除法

GC过程开启STW,从root根节点出发标记所有可达节点,停止STW后回收未标记的节点。
在这里插入图片描述
弊端:在整个GC期间需要STW,将整个程序暂停,有极大的性能损耗。

v1.5 三色标记法

对象分为黑、白、灰三种颜色。最终,可达对象都会变成黑色,不可达对象为白色,灰色为中间过渡态。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后回收不可达的白色对象,GC操作完成。

在这个过程中仍然需要进行STW,因为在每次GC操作过程中,只有灰色对象下游的白色对象会被扫描(判断是否需要回收)。如果在GC过程中由于程序的运行出现黑色对象引用白色对象的情况,那么存活的白色对象会被GC程序误杀。

在这里插入图片描述
图:原先2->3,经过程序运行,变成6->3。

Golang是如何解决这个STW问题的呢?
其实总结来看,在三色标记法的过程中对象丢失,需要同时满足下面两个条件:

条件一:白色对象被黑色对象引用
条件二:灰色对象与白色对象之间的可达关系遭到破坏

看来只要把上面两个条件破坏掉一个,就可以保证对象不丢失,所以我们的golang团队就提出了两种破坏条件的方式:强三色不变式和弱三色不变式。

强三色不变式

规则:不允许黑色对象引用白色对象

破坏了条件一: 白色对象被黑色对象引用
解释:如果一个黑色对象不直接引用白色对象,那么就不会出现白色对象扫描不到,从而被当做垃圾回收掉的尴尬。

在这里插入图片描述

弱三色不变式

规则:黑色对象可以引用白色对象,但是白色对象的上游必须存在灰色对象

破坏了条件二:灰色对象与白色对象之间的可达关系遭到破坏

解释: 如果一个白色对象的上游有灰色对象,则这个白色对象一定可以扫描到,从而不被回收

在这里插入图片描述

屏障机制

Golang团队遵循上述两种不变式提到的原则,分别提出了两种实现机制:插入写屏障删除写屏障

插入写屏障:仅在堆上生效

规则:当一个对象引用另外一个对象时,将另外一个对象标记为灰色。

满足:强三色不变式。不会存在黑色对象引用白色对象

插入屏障仅会在堆内存中生效,不对栈内存空间生效,因为栈空间操作过于频繁,会引发性能问题。

弊端:在一次正常的三色标记流程结束后,由于插入写屏障不会对栈空间起作用,仍有可能在栈空间出现黑色对象引用白色对象的情况,需要对栈上重新进行一次stw,然后再rescan一次。

删除写屏障

规则:在删除引用时,如果被删除引用的对象自身为灰色或者白色,那么被标记为灰色。

满足弱三色不变式。灰色对象到白色对象的路径不会断

解释:白色对象始终会被灰色对象保护

弊端:就是一个对象的引用被删除后,即使没有其他存活的对象引用它,它仍然会活到下一轮。如此一来,会产生很多的冗余扫描成本,且降低了回收精度。

在这里插入图片描述

对比插入写屏障和删除写屏障:

插入写屏障:

插入写屏障哪里都好,就是栈上的操作管不到,所以最后需要对栈空间进行stw保护,然后rescan保证引用的白色对象存活。

删除写屏障:

在GC开始时,会扫描记录整个栈做快照,从而在删除操作时,可以拦截操作,将白色对象置为灰色对象。
回收精度低。

v1.8 混合写屏障机制

混合屏障机制的核心定义:

GC刚开始的时候,会将栈上的可达对象全部标记为黑色。

GC期间,任何在栈上新创建的对象,均为黑色。

上面两点只有一个目的,将栈上的可达对象全部标黑,最后无需对栈进行STW,就可以保证栈上的对象不会丢失。有人说,一直是黑色的对象,那么不就永远清除不掉了么,这里强调一下,标记为黑色的是可达对象,不可达的对象一直会是白色,直到最后被回收。

堆上被删除的对象标记为灰色

堆上新添加的对象标记为灰色

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

Golang v1.3之前采用传统采取标记-清除法,需要STW,暂停整个程序的运行。

在v1.5版本中,引入了三色标记法和插入写屏障机制,其中插入写屏障机制只在堆内存中生效。但在标记过程中,最后需要对栈进行STW。

在v1.8版本中结合删除写屏障机制,推出了混合屏障机制,屏障限制只在堆内存中生效。避免了最后节点对栈进行STW的问题,提升了GC效率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值