当前位置: 首页 > article >正文

golang的GC(三色标记法+混合写屏障)学习笔记

一、标记清除法

在go1.3之前,go的GC是要先执行STW,然后给可达对象和不可达对象做上标记,然后再把不可达对象全部删掉。使用STW会使程序停止运行一定的时间,影响用户的使用,发生抖动。

二、三色标记法:

在go1.5之后出现了三色标记法,即扫描栈上和堆上的对象,没有被扫描到的对象为白色,第一次扫描会将root set,也就是根节点置为灰色,第二次遍历时,遍历的是灰色节点,此时会将灰色节点下面的可达节点置为灰色,遍历到的灰色节点变为黑色。最后遍历完成时,只剩下白色和黑色,白色对象将会被回收

如果三色标记法没有stw的话,在程序的运行过程中,可能会有堆上的黑色节点引用栈上的白色节点,栈上的这个白色节点原本是被栈上的灰色节点所引用,但是接着又删除掉了,这时,由于GC不会再遍历黑色节点下面的白色节点了,但是这个白色节点又是被引用的,这样就导致一个被引用的对象被回收掉了。

为了解决这个问题,引入了强三色不变式和弱三色不变式

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

弱三色不变式:允许黑色对象引用白色对象,但这个白色对象必须被灰色对象引用,或者这个白色对象的最上层是个灰色对象。

插入写屏障(即实现了强三色不变式)

如果一个对象被引用,那么这个对象就会变为灰色对象

缺点:为了不耽误栈的运行效率,栈空间不会使用插入写屏障,所以在最后需要将栈上的对象全部置为白色并进行stw防止黑色对象再引用其他对象。这种情况还是需要短暂的stw

删除写屏障(即实现了弱三色不变式):删除一个对象,如果这个对象是灰色或白色,那么会将这个对象置为灰色  

缺点:被删除的对象会被置为灰色,最后可能没有对象引用,这时就需要再对这些对象进行多一轮的扫描

go1.8之后的GC:三色标记法+混合写屏障

这个版本的垃圾回收机制还是需要STW,不过它的时间是微妙级别的,可以忽略不计,因为这个STW是在完成标记并进行最后收尾的时候执行的,所以时间很短。

结合插入写屏障和删除写屏障,诞生混合写屏障,它的步骤如下:

1、在一开始就将栈上的可达对象全部置为黑色,以及将新增的对象置为黑色

2、插入一个新对象,新对象变为灰色

3、删除一个新对象,新对象变为灰色

总结

在go的不同版本中使用的垃圾回收机制是不一样的,go1.3之前使用的是标记清除法,这个机制会有较长时间的STW,对程序运行会造成比较大的影响;go1.5后的版本采用的是三色标记法,首先会将rootset的节点置为灰色,然后再遍历灰色节点下的白色节点,如果白色节点可达,那么将白色节点置为灰色,将原本的灰色节点置为黑色,在没有STW的情况下,三色标记法出现一种情况,黑色节点引用白色节点,而这个白色节点是被灰色节点引用的,接着灰色节点又删除了白色节点,导致白色节点无法被遍历到并置为灰色,最终导致对象被回收,为了解决这个问题引入了强三色不变式和弱三色不变式来阻止以上情况的发生,最后是采用插入写屏障和删除写屏障来实现强弱三项不变式。go1.8之后的GC是使用三色标记法+混合写屏障机制来实现的,通过这几个步骤来操作:

1、刚开始垃圾回收时,将栈空间的对象全部置为黑色

2、在栈空间上创建的对象默认置为黑色

3、删除对象时,将对象置为灰色

4、插入对象时,将对象置为灰色

在栈空间上不开启屏障,在堆空间上开启混合写屏障。对于一些没有被根节点引用的黑色节点,最后会在下一轮扫描中被回收


http://www.kler.cn/a/306204.html

相关文章:

  • C++中的std::tuple和std::pair
  • 如何使用 Web Scraper API 高效采集 Facebook 用户帖子信息
  • 【2024软考架构案例题】你知道 Es 的几种分词器吗?Standard、Simple、WhiteSpace、Keyword 四种分词器你知道吗?
  • java八股-jvm入门-程序计数器,堆,元空间,虚拟机栈,本地方法栈,类加载器,双亲委派,类加载执行过程
  • 提取神经网络数学表达式
  • 32位、64位、x86与x64:深入解析计算机架构
  • 第一篇---滑动窗口最大值、前 K 个高频元素
  • 初识爬虫2
  • Linux删除SSH生成的密钥对
  • 探索Python的Excel世界:openpyxl的魔法之旅
  • 【homebrew安装】踩坑爬坑教程
  • 路由策略原理与配置
  • C#笔记11 获取线程及其信息,什么是优先级、单元状态、线程状态、执行状态、线程名称以及其他属性?
  • 一文速通calcite结合flink理解SQL从文本变成执行计划详细过程
  • Kubernetes Pod镜像的3种状态
  • STM32-UART配置注释
  • 标准库标头 <bit>(C++20)学习
  • 计算机网络 --- 计算机网络性能【七大性能指标】
  • 如何精确统计Pytorch模型推理时间
  • c语言写的环形队列
  • emWin5的图片半透明之旅
  • 高级java每日一道面试题-2024年9月12日-架构篇[DDD领域驱动篇]-如何使用领域驱动设计(DDD)中的事务脚本模式?
  • Spring4-IoC2-基于注解管理bean
  • comfyui中,sam detector与yoloworld图像分割算法测试以及影响
  • [极客大挑战 2019]PHP
  • 1、常用的数据库、表操作