Goland GC

devtools/2024/10/18 14:15:53/

Goland GC

  • 引用
  • Go 1.3 mark and sweep 标记法
  • Go 1.5 三色标记法
      • 屏障机制
        • 插入屏障
        • 删除写屏障
        • 总结
  • Go 1.8 混合写屏障(hybrid write barrier)机制
  • 总结

引用

https://zhuanlan.zhihu.com/p/675127867

  • Garbage Collection,缩写为GC,一种内存管理回收的机制

Go 1.3 mark and sweep 标记法

流程:

  1. 暂停程序
  2. 从入口标记所有可达的对象
  3. 删除不可达的对象
  4. 恢复程序
  • 这种方式存在一个STW(stop the world)时间。

Go 1.5 三色标记法

  • 解决上个版本存在STW的问题。
  • 三个颜色:
    白色:尚未访问过
    黑色对象已访问过,而且本对象 引用到 的其他对象 也全部访问过了
    灰色对象已访问过,但是本对象 引用到 的其他对象 尚未全部访问完。全部访问后,会转换为黑色。

流程:

  1. 每次新创建的对象,默认的颜色都是标记为“白色”
    在这里插入图片描述
    上图所示,我们的程序可抵达的内存对象关系如左图所示,右边的标记表,是用来记录目前每个对象的标记颜色分类。这里面需要注意的是,所谓“程序”,则是一些对象的根节点集合。所以我们如果将“程序”展开,会得到类似如下的表现形式,如图所示。

在这里插入图片描述
Root Set根节点集合:程序运行到当前时刻的栈和全局数据区域。

BFS遍历一层,使用两个数组:灰色数组和黑色数组。

  1. 把白色可达的1,4加入灰色。
  2. 灰色遍历后变成黑色,即 1,4变成黑色。
  3. 灰色遍历到的2,7由白转灰。
  4. 反复遍历灰色直至没有灰色。
  5. 回收白色。

但如果GC过程中程序在运行,上述引用关系会实时改变,则此方法会误删白色对象。
在运行时能导致错误GC的场景是:

  1. 白色被黑色所引用
  2. 灰色到白色的引用失效

白色被黑色所引用

屏障机制

谷歌团队引入了强弱三色不变式
强制不允许黑色引用白色
:所有被黑色对象引用的白色对象都处于灰色保护状态

在这里插入图片描述
弱三色不变式强调,黑色对象可以引用白色对象,但是这个白色对象必须存在其他灰色对象对它的引用,或者可达它的链路上游存在灰色对象。 这样实则是黑色对象引用白色对象,白色对象处于一个危险被删除的状态,但是上游灰色对象的引用,可以保护该白色对象,使其安全。

为了遵循上述的两个方式,GC算法使用两种屏障方式:插入屏障删除屏障

插入屏障

具体操作: 改色:A引用B时,B改为灰色。(重新参与到bfs里)
满足: 强三色不变式. (不存在黑色对象引用白色对象的情况了, 因为白色会强制变成灰色)
黑色对象的内存槽有两种位置, 栈和堆. 栈空间的特点是容量小,但是要求相应速度快,因为函数调用弹出频繁使用, 所以“插入屏障”机制,在栈空间的对象操作中不使用. 而仅仅使用在堆空间对象的操作中.

这样可以避免堆中操作出现白色对象误删的情况。至于栈中操作,开启STW确保安全性。

这样此方案可以解决在堆操作不需要开启STW。
在这里插入图片描述
在这里插入图片描述

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

删除写屏障

删除写屏障是指:被删除引用关系的对象,如果自身为灰色或者白色,那么被标记为灰色。这一点其实就是为了满足弱三色不变式。
满足: 弱三色不变式. (保护灰色对象到白色对象的路径不会断)
比如A 此时引用了B对象,但是此时A要删除和对象B的引用关系此时。此时如果B对象是白色对象那么B对象会被置为灰色。还有一种情况就是
A对象之前引用了B对象此时,此时A更换了引用关系引用C也就是A对象和B对象之间的引用关系被删除掉了。此时B对象会被置为灰色。
在这里插入图片描述
此时对象1想要删除和对象5之间的引用关系,此时就会触发删除写屏障。

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

  • 正常删除1到5的引用后,GC应该把 2 3 5都回收了。但是因为保护机制,保留了235,在下一轮GC再处理。
总结

至此可以解决堆上新增引用的STW的问题,还有堆和栈上删除引用不需要STW,只需要下一次GC来回收。
还遗留了栈上新建引用导致的STW问题。

Go 1.8 混合写屏障(hybrid write barrier)机制

  • 混合写屏障一开始将栈上对象全部标记为黑色
  • 在GC期间任何在栈上创建的对象均为黑色。
  • 被删除引用的对象均标记为灰色
  • 被添加引用的对象均标记为灰色
  • 栈不开启屏障机制

也就是BFS对栈上对象的初始化总为黑色,运行时的引用关系变化后的子节点总是标记为灰色,参与到下一轮的BFS里。
主要为了满足弱三色不变式。注意混合写屏障是Gc的一种屏障机制,所以只是当程序执行GC的时候,才会触发这种机制。
在这里插入图片描述
GC刚开始所有对象都是白色的,然后第一步我们扫描栈区将栈上的对象全部标记为黑色

在这里插入图片描述

在这里插入图片描述
运行时 1 新建了到7的引用。
在这里插入图片描述
7会被置灰,后续运行时4删除7的引用直接删即可。

在这里插入图片描述
在栈上新增 9,按照规则在栈上创建的对象均为黑色对象。
在这里插入图片描述
新增9到3的引用 直接添加即可。
在这里插入图片描述
2删除3的引用关系,在栈上删除即可。不存在误删

在这里插入图片描述
在这里插入图片描述
新建引用关系10-7,会让7置灰,避免7被删除

在这里插入图片描述
4引用2,2本来就是黑色不影响。

在这里插入图片描述
对象1删除和对象2之间的引用关系直接删了就可以,对象4删除和对象7之间的引用关系此时由于是在堆上所以了触发了这个混合写屏障机制将对象7置为灰色。
下一轮GC会处理 7 6 11.

总结

Go 1.3版本:普通标记清除法,整体过程需要启动STW,效率极低。
Go 1.5版本: 三色标记法, 堆空间启动写屏障,栈空间不启动,全部扫描之后,需要重新扫描一次栈(需要STW),效率普通
Go 1.8版本:三色标记法,混合写屏障机制, 栈空间不启动,堆空间启动。整个过程几乎不需要STW,效率较高。


http://www.ppmy.cn/devtools/42013.html

相关文章

Android系统不同版本存储权限

一、Android存储简介 Android系统分为内部存储和外部存储 从Android6.0开始不断在更新存储(读写)权限,除了在AndroidManifest.xml文件里声明,app运行时也要动态申请使用对应的权限 提醒:应用私有存储不需要动态申请权…

计算机组成原理第六章 计算机的运算方法

文章目录 6.1 无符号数和有符号数 6.1.1 无符号数 6.1.2 有符号数 1、原码 2、补码 3、反码 4、移码 5、小结 6.2 数的定点表示和浮点表示 6.2.1 定点表示 6.2.2 浮点表示 1、浮点数的表现形式 2、浮点数的表示范围 3、浮点数的规格化 6.2.3 定点数和浮点数的比…

nmap端口扫描工具——LInux

目录 系统版本: nmap主要功能 安装: nmap命令使用方法

Leetcode - 周赛397

目录 一,3146. 两个字符串的排列差 二,3147. 从魔法师身上吸取的最大能量 三,3148. 矩阵中的最大得分 四,3149. 找出分数最低的排列 一,3146. 两个字符串的排列差 本题就是求同一个字符在两个字符串中的下标之差的…

代码复现|Demucs Music Source Separation

一、背景介绍 Demucs是一个开源的音源分离项目。 Demucs在算法层面前后经历了三次大版本的进化,最原始的V1版本是:编解码LSTM。具体算法原理图如下所示。该版本在时域进行音源分离。关于阅读笔记请点击这篇文章。 V1版本原理图 V2版本是同时使用时域和频…

Java中的数组、Set、List、Map类型的互相转换总结

序言 数组、Set、List、Map是Java语言非常常用的几种数据类型,他们之间存在着千丝万缕的联系。关于底层的数据结构我这里就不再多说啦,直接从应用出发,总结他们之间的转换方法,并给出推荐方法。 大家可以点赞收藏等到需要的时候…

NIUKE Python:Python入门(上)

01 输入输出 NP1 Hello World! 将字符串 Hello World! 存储到变量str中,再使用print语句将其打印出来 strHello World! print(str) NP2 多行输出 将字符串 Hello World! 存储到变量str1中,再将字符串 Hello Nowcoder! 存储到变量str2中,再…

ABAP 第四代增强

文章目录 ABAP 第四代增强增强点创建增强点增强点的实施 增强部分(ENHANCEMENT-SECTION)创建增强部分(ENHANCEMENT-SECTION)运行结果 增强部分的实施 隐式增强选项显示/隐藏 隐式增强选项隐式增强的实施运行结果 STATIC类型的增强…