go垃圾回收机制(三色标记法)& 屏障机制

go垃圾回收机制(三色标记法)

V1.3之前标记清除法:

Go 1.0

串行标记清除 + STW

Go 1.3

在Go 1.3版本中垃圾回收算法采用 并发标记清除+STW

缺点:

  • STW,让程序暂停,导致程序出现卡顿;
  • 标记需要扫描整个heap;
  • 清除数据会产生heap碎片;

三色标记法

根据root set(根节点集合)来寻找根节点,在执行GC的时候,Root Set根节点集合被划分为栈区域和堆区域,对栈上对象不用屏障,对堆上对象使用屏障,并行的执行三色标记回收算法;

我们把遍历对象图过程中遇到的对象,按“是否访问过”这个条件标记成以下三种颜色:

  • 白色:尚未访问过。
  • 黑色:本对象已访问过,而且本对象 引用到 的其他对象 也全部访问过了。
  • 灰色:本对象已访问过,但是本对象 引用到 的其他对象 尚未全部访问完。全部访问后,会转换为黑色。

步骤:

  • 第一步,只要是创建的对象都标记为白色;
  • 第二步,每次GC回收开始,然后从根节点开始遍历所有对象,把遍历到的对象从白色放到灰色集合;
  • 第三步遍历灰色集合,将灰色对象引用到的对象从白色集合放到灰色集合,之后将此灰色对象放到黑色集合;
  • 第四步,重复第三步直到灰色集合为空;
  • 第五步,回收所有白色标记的对象(垃圾回收);

在不STW的情况下保证不丢失对象

强弱三色不变式:

(二者满足其一即可)

强三色不变式:强制性不允许黑色对象引用白色对象;

弱三色不变时:保护灰色对象到白色对象的路径不会断;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7X5ekXFZ-1679280625561)(D:\文件\我是桌面\Golang\15.png)]

屏障机制是基于强弱三色不变式的

屏障机制(即在操作中添加一些触发机制):

由于栈对速度的要求比较高,所以栈上不启用屏障机制,

插入写屏障——对象被引用时触发的机制

  • 在A对象引用B对象时,B对象被标记为灰色(满足强三色不变式)

为了保证栈的速度,如果为栈上的对象增加插入屏障,会大幅度增加引用对象的性能,所以栈空间不触发插入屏障,堆空间会触发插入屏障,而在回收白色之前会重新遍历扫描一次栈空间,此时添加STW暂停来保护栈,防止外界干扰(有新的白色被黑色添加);

插入屏障的不足:在结束的时候需要开启STW重新扫描栈,但是所需时间较短(10-100ms);

删除写屏障——对象被删除时出发的机制

  • 被删除的对象如果为灰色或者白色,那么被标记为灰色(满足弱三色不变式)

(说明:删除相当于用nil来替换被删除的对象,将被删除的对象置为灰,此时该对象即使被删除也会被暂时保留下来,避免该对象被其他的对象使用)

删除屏障的不足:回收精度低,一个对象即使被删除了最后一个指向它的指针也依旧可以活过这一轮,在下一轮GC中被删除(宁可放过也不错删);

混合写屏障

  • GC开始将栈上的对象全部扫描并标记为黑色;
  • GC期间,任何在栈上创建的新对象,均为黑色(避免进行二次扫描);
  • 被删除的对象标记为灰色;
  • 被添加的对象标记为灰色;

Go的所有GC实现版本都没用单独用过删除写屏障,作者在讲删除写屏障的时候应该只是单纯想表达,如果单独用删除写屏障的话大概是这样一个效果。但是事实上Go的GC,只有从标记清除–插入写屏障–混合写屏障,且插入写屏障和混合写屏障对栈上都不操作;

在Go使用的混合写屏障中是不会对栈空间进行写屏障的,栈上的对象在一开始就全部标记为黑色,并且在GC过程中新创建的对象也是黑色的,可能错放但不错杀;

猜你喜欢

转载自blog.csdn.net/SFDWU3QVG/article/details/129663007