Golang底层原理剖析之垃圾回收GC(一):https://developer.aliyun.com/article/1417141
删除写屏障
介绍
行为->被删除的对象,如果自身为灰色或者白色,那么被标记为灰色
满足->弱三色不变式. (保护灰色对象到白色对象的路径不会断)
这种方式的回收精度低,一个对象即使被删除了最后一个指向它的指针也依旧可以活过这一轮,在下一轮GC中被清理掉。
堆栈皆可用弱三色不变式!
图示
两种屏障的缺点
- 插入写屏障:结束时需要STW来重新扫描栈,标记栈上引用的白色对象的存活;
- 删除写屏障:回收精度低,GC开始时STW扫描堆栈来记录初始快照,这个过程会保护开始时刻的所有存活对象。
混合写屏障
Go V1.8版本引入了混合写屏障机制(hybrid write barrier),避免了对栈re-scan的过程,极大的减少了STW的时间。结合了两者的优点。
注意混合写屏障是GC的一种屏障机制,所以只是当程序执行GC的时候,才会触发这种机制
Golang中的混合写屏障满足弱三色不变式,结合了删除写屏障和插入写屏障的优点,只需要在开始时并发扫描各个goroutine的栈,使其变黑并一直保持,这个过程不需要STW,而标记结束后,因为栈在扫描后始终是黑色的,也无需再进行re-scan操作了,减少了STW的时间。
步骤
- GC开始将栈上的对象全部扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW)
- GC期间,任何在栈上创建的新对象,均为黑色
- 被删除的对象标记为灰色
- 被添加的对象标记为灰色
满足->变形的弱三色不变式
这里我们注意, 屏障技术(步骤三四)是不在栈上应用的,因为要保证栈的运行效率
这里我们注意, 屏障技术(步骤三四)是不在栈上应用的,因为要保证栈的运行效率
混合写屏障的场景分析
对象被堆对象删除引用,被栈对象引用
对象被栈对象删除引用,被另一个栈对象引用
对象被堆对象删除引用,被另一个堆对象引用
对象被栈对象删除引用,被堆对象引用
总结
以上便是Golang的GC全部的标记-清除逻辑及场景演示全过程。
GoV1.3 - 普通标记清除法,整体过程需要启动STW,效率极低。
GoV1.5 - 三色标记法, 堆空间启动写屏障,栈空间不启动,全部扫描之后,需要重新扫描一次栈(需要STW),效率普通
GoV1.8 - 三色标记法+混合写屏障机制, 栈空间不启动,堆空间启动。整个过程几乎不需要STW,效率较高。
几乎不需要STW:GC标记准备阶段和GC标记结束阶段还是需要STW 来通知所有的Goroutine 我进入垃圾回收阶段了,然后启用/关闭屏障机制,但是这个耗时很小,一般几十微秒
混合写屏障的标记过程中不再需要STW,标记准备 和 标记结束 还是需要STW的