golang垃圾回收 三色清除
Posted better_hui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang垃圾回收 三色清除相关的知识,希望对你有一定的参考价值。
目录
标记清除
算法
1、标记 (mark phase)
stw ,找到所有不可达的对象,做好标记
2、清除 (mark phase)
清除未标记的对象
缺点
1、stw , 暂停整个程序
2、标记需要扫描整个heap
3、清除数据会产生碎片
优化
1.3版本前,整个过程都在stw范围内
1.3做了优化,尽在标记阶段暂停。
三色标记
原理
三色标记的过程就是确认哪些对象不可达的过程。具体的过程如下:
1、所有新创建的对象都标记为白色
2、从根节点出发,能够直接到达的对象,标记为灰色
3、从灰色节点出发,可以到达的白色对象标记为灰色,原灰色节点标记为黑色。循环往复直至灰色标记为空
4、回收所有依然是白色标记的对象。
问题:
在三色标记中,黑色节点是不会重复扫描的,所以,如果没有stw就会出现一下两个问题:
1、白色对象被黑色对象引用 (白色对象会被删除)
2、灰色对象与其可达的白色对象之间的链路被破坏(破坏点之后的白色对象会被清除,因为链路断了扫描不到)
stw是解决以上问题的最好办法,但是stw不是我们想要的,所以出现了屏障技术
屏障技术
原理
GC过程中,满足以下条件之一,那么对象就是安全的:
1、强三色不变式 , 即不存在黑色对象引用白色对象的指针
2、弱三色不变式 ,即黑色对象引用的白色对象,处于灰色对象保护状态之下(扫描链路可达)
写屏障
写屏障,就是强三色不变式的实现:在对象A引用对象B的时候,B对象标记为灰色。
栈空间操作频繁是没有写屏障的,所以需要stw保护。
流程如下:
但是如果栈不添加,当全部三色标记扫描之后,栈上有可能依然存在白色对象被引用的情况(如上图的对象9). 所以要对栈重新进行三色标记扫描, 但这次为了对象不丢失, 要对本次标记扫描启动STW暂停. 直到栈空间的三色标记结束.
最后将栈和堆空间 扫描剩余的全部 白色节点清除. 这次STW大约的时间在10~100ms间.
缺点:栈空间没有写屏障的保护,所以仍然需要stw的保护。
删除屏障
删除屏障是弱三色不变式的实现,即被删除的对象,如果自身为灰色或者白色 , 那么标记为灰色。
过程:
缺点:
1、开始阶段STW整个栈空间
2、会有浮动垃圾,因为被断开的链路有可能是垃圾,但是仍然被置为灰色了。
混合写屏障
针对写屏障和删除屏障的缺点,1.8版本引入了混合写屏障机制,避免了对栈的re-scan的过程,极大的减少STW时间。
优点:全程无STW , 但是针对单个goroutine来讲 , 是有STW的
缺点:继承了删除屏障的收集精度问题
简要流程:
1、GC并发标记所有栈空间的对象为黑色
2、GC期间任何栈上的新对象,标记为黑色
3、被删除的对象标记为灰色
4、新添加的对象标记为灰色
四种场景:
1、堆对象被一个堆对象删除引用,成为栈对象的下游:因为被引用的对象是堆空间的,触发写屏障,标记为灰色
2、堆对象被一个堆对象删除引用,成为某个堆对象的下游 , 同样触发写屏障机制
对象从一个栈对象删除引用,成为另一个堆对象的下游
对象被一个栈对象删除引用,成为另一个栈对象的下游
以上是关于golang垃圾回收 三色清除的主要内容,如果未能解决你的问题,请参考以下文章