golang 垃圾回收-三色标记法(白话版)

news2025/1/18 6:48:42

对于golang 垃圾回收的了解,我理解更多的就是了解,实际做项目能用到垃圾回收的知识点不多,但有些晦涩难懂的语言,是我们的绊脚石,对于技术怎么能理解就怎么记忆。

1. golang垃圾回收的基础:标记(Mark)、清扫(Sweep)

1)首先把我们的对象简单归个类,有些对象包含基础类型,这类对象回收比较省心,只要该对象没人调用,那就可以回收了。

type aa struct {
	A int
	B int
}

2)还有对象中包含指针,指针指向另一个对象,这种对象回收 不能只考虑本对象,还要考虑指向的对象,如果父对象都没有回收,却把指针指向的对象删除,那妥妥的内存泄漏。

type aa struct {
	A *bb
	B int
}

type bb struct {
	X int
	Y int
}

3)假设应用代码片段如下(不要较真这段程序的对象在栈上分配,示意):

	a := aa{}
	b1 := &bb{
		X: 1,
		Y: 2,
	}
	b2 := &bb{
		X: 3,
		Y: 4,
	}
	a.B = b1
	a.B = b2

系统有三个对象分别为a、b1、b2
![在这里插入图片描述](https://img-blog.csdnimg.cn/80abf3e538ce4858a9fefc8cee713f30.png
4)开始标记根对象,假设跟对象为a为黑色、由于a与b2是父子对象,也标记为黑色。
在这里插入图片描述
5)最后发现b1 是白色的,执行清扫流程,然后就回收了。

问题:可以看出标记、清扫逻辑清晰,实现简单,真实GC界的翘楚! 但是,这里有个严重的问题,如果刚扫描完成b2标记为黑色,执行a.B = b1代码,a又指向了b1,但b1没有被扫描,非常幸运b1被回收了。。。

为了解决这个问题,很简单从源头解决,不让a.B = b1 代码执行就行了,也就是STW。但对标记整个流程STW,性能自然是不高的。

2. 三色标记法

1)三色标记法介绍

对上述标记、清扫流程改进,三色标记法。

白色:没有被标记的对象
灰色:被扫描到的对象
黑色:所有子对象都被扫描后,由灰色变成黑色。

还是上面的例子:

  • 扫描到a的样子,a变成灰色。
    在这里插入图片描述
  • 扫描到b2的样子,b2 变成灰色
    在这里插入图片描述
  • 扫描完成后的样子,a、b2 都变成黑色
    在这里插入图片描述
  • 执行清扫流程,将白色的对象回收。

这效果非常棒,成功实现对象回收!!但是… 这和上面的标记、清扫没啥区别啊,STW问题一个没解决,还换了好几个颜色,崩溃啊!!

2)三色不变性

仔细思考,一个对象被错误回收需要两个必要条件,也就是只要满足下面条件,就会发生内存泄露。
1)强三色不变性:如果出现一个黑色对象指向白色对象。
2)弱三色不变性:白色对象没有一条灰色对象指向他。这句话有点绕,场景:如果一个白色的对象,没有任何一条灰色的对象指向他,则满足第二个条件。

我们上面的案例分析,满足两个条件,黑色指向白色,且没有灰色指向白色,出现内存泄露。
在这里插入图片描述
那么只要我们想办法破坏这两个不变性中的一个,就不会出现内存泄露。

3)写屏障

屏障技术网上有很多,这里我们抽取和我们有关的描述,可以在内存操作前执行特定的逻辑。注意:内存在golang程序中分为堆、栈,golang是对堆使用屏障技术,可能是技术实现难度大,毕竟每次栈操作调用其他函数处理、还要保证性能。

插入写屏障

目标:打破强三色不变性,也就是不让对象标记期间,出现黑色指向白色的情况。当有白色对象挂到黑色对象下面时,将白色变成灰色。

还是按照上面的案例,当我们开始垃圾回收的时候,不进行STW,直接开启写屏障,当执行a.B = b1命令时触发写屏障逻辑,将b1 标记为灰色。最终如下图所示:
在这里插入图片描述

有了插入写屏障,打破强三色不变性,对象不会错误回收,也不用STW,完美。但是屏障技术应用在堆上,并没有应用在栈上,假设a对象分配在栈上,那么当a.B = b1执行时,不会触发写屏障,那可咋弄?
答:在标记阶段需要STW,扫描栈上指针后,并发标记。这种方式虽然也有STW,但范围上已经小了很多,毕竟堆标记的时候没有STW。这种GC方式在go1.5版本使用。

删除写屏障

目标:我们再思考能否从弱三色不变性下手,打破弱三色不变性。即在标记期间如果有指向白色对象的对象更改引用关系,则直接将该白色对象标记为灰色。上面的例子不够看了,我们再换个例子。

场景:
1)a1、b1对象已经标记完毕
2)a2 已经标记完毕,正在标记b2 的 时候,执行a.B = b2,如果没有插入写屏障,则b2仍然未被标记。
3)b2被残忍回收了。
在这里插入图片描述
删除写屏障:当a2 与 b2 解除依赖关系时,触发删除写屏障,b2标记为灰色。

在这里插入图片描述
通过删除写屏障也可以防止内存泄露,但我们还未讨论栈上指针如何处理。

删除写屏障-栈指针处理
1)还是上面的例子,假设a1、a2是栈上对象,上面的例子无法触发删除写屏障,b2内存泄露。
2)a2与b2 解除关系后,b2 与b1进行绑定,如果没有插入写屏障,即使b1是堆对象,也无法触发屏障技术。
在这里插入图片描述
上面两种情况分别讨论下:
1)如果能将a2上的指针对象改为a1,说明a1、a2 在同一个goroutine,每个goroutine有独立的栈空间,同一个goroutine发生指针改变,那么后续对栈进行扫描的时候,可以以协程为单位进行STW,还可以并发扫描,时间少很多。
2)这种情况如果能够引入插入写屏障,b2就可以标记为灰色对象。

混合写屏障

go1.8,实现插入写屏障和删除写屏障,STW期间只需要并发检查每个goroutine对象指针变化情况。大大减少STW的时间。

参考:https://cloud.tencent.com/developer/article/2108449

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/142339.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESNI 和ECH的前世今生

这边文章中提到过虽然 TLS 能够加密整个通信过程,但是在协商的过程中依旧有很多隐私敏感的参数不得不以明文方式传输,其中最为重要且棘手的就是将要访问的域名,即 SNI(Server Name Indication)。同时还有用于告知客户端…

javaEE高阶---MyBatis

一 : 什么是MyBatis MyBatis是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库的工具.MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获取结果集的动作 . MyBatis …

[oeasy]python0037_终端_terminal_电传打字机_tty_shell_控制台_console_发展历史

换行回车 回忆上次内容 换行 和 回车 是两回事 换行 对应字节0x0ALine-Feed 水平 不动垂直 向上喂纸 所以是 feed 回车 对应字节0x0DCarriage-Return 垂直 不动水平 回到纸张左侧 可移动的打印头 运输字符 的 装置 (Carriage)回到 行首 所以是 Return tty、terminal、shell、…

【视觉SLAM】DM-VIO: Delayed Marginalization Visual-Inertial Odometry

L. v. Stumberg and D. Cremers, “DM-VIO: Delayed Marginalization Visual-Inertial Odometry,” in IEEE Robotics and Automation Letters, vol. 7, no. 2, pp. 1408-1415, April 2022, doi: 10.1109/LRA.2021.3140129. 论文阅读方法:Title,Abstract…

百趣代谢组学文献分享:学科交叉研究,微生物回收重金属机制研究

发表期刊:Environment International 影响因子:7.297 发表时间:2019年 合作单位:福建农林大学 百趣代谢组学文献分享,该文章是BIOTREE协助客户2019年发表在Environment International上的关于微生物回收重金属机制研…

Tomcat的Connector启动过程分析

一. 前言 前面分析了tomcat的整体架构和tomcat的启动过程,在分析启动过程的时候只讲了整体的启动过程,本篇来重点分析一下tomcat的Connector(连接器)组件的启动过程。 二.从Connector的构造开始 那么org.apache.catalina.connector.Connector是在什么…

文献学习06_利用句法指示符和句子上下文加强关系抽取

论文信息 Subjects: Computation and Language (cs.CL) (1)题目:Enhancing Relation Extraction Using Syntactic Indicators and Sentential Contexts (利用句法指示符和句子上下文加强关系抽取) (2&…

论文精读:RPM-Net: Robust Point Matching using Learned Features

论文地址:https://arxiv.org/pdf/2003.13479.pdf 点云配准任务 点云配准可以当做一个基础的上游任务,根据从不同视角下获取的点云数据配准为完整的点云数据,下游任务众多 基本任务:求一个变换矩阵,使得两个具有未知点的点云数据重合。 刚性与非刚性: 刚性配准:旋转和平…

Leetcode 121买卖股票的最佳时机

题目描述: 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔…

solr集群配置(使用solr自带的Jetty实现集群配置)

看了很多的资料发现基本集群搭建都是通过tomcat的方式实现的,但是在高版本的solr中,可以通过solr自带的jetty实现集群的搭建 准备 1.虚拟机安装linux 2.安装jdk 3.下载solr并解压 步骤 1.进入到解压后solr的bin目录下,并执行 ./solr -e clo…

赛狐ERP | 如何高效管理亚马逊广告!用这款亚马逊ERP就够了!

亚马逊的广告管理是是每一位亚马逊运营的必修课,除自然流量外,广告来带的流量与转化占比都极高,广告做活了,就是打虎上山;广告搞砸了,就是骑虎难下:不开广告吧没有流量卖不动、开了广告吧财务账…

#B. 部落联盟

一,题目Description在草原上有N个部落,每个部落都有其坐标(xi,yi)每个部落都有个武力值,可正可负由于部落间只能通过马匹来传递信息于是只有当两个部落间的距离为1的时候,两个部落才有可能进行联系,距离计算公式为abs(xi-xj)abs(y…

人生的喜悦、不快与成长,都在那一篇篇的文字中得到记录 | 2022 年终总结

又是一年的总结,不知道自己今年又该写点什么。但提笔总是好的,也算对今年的一个交代和对未来的一份期许。窗外的阳光正好,对面楼的敲打声叮叮咚咚,窗台上的两只猫睡得依旧奔放和舒适。这样一个看似美好的下午,一个平凡…

Internet Download Manager2023最好用的HTTP下载神器

Internet Download Manager 介绍2023最佳下载利器。Internet Download Manager (简称IDM) 是一款Windows 平台功能强大的多线程下载工具,国外非常受欢迎。支持断点续传,支持嗅探视频音频,接管所有浏览器,具有站点抓取、批量下载队…

机器学习100天(二十六):026 k近邻分类算法-理论

机器学习100天,今天讲的是:K 近邻分类算法-理论。 《机器学习100天》完整目录:目录 一、什么是 K 近邻算法 K 近邻算法也叫 KNN(k-Nearest Neighbor)算法,它是一个比较成熟也是最简单的机器学习算法之一。K 近邻分类算法的思路是:如果一个样本在特征空间中与 K 个实例最…

FastAPI集成Socket.io坑点汇集和技术选型

背景 单纯的 websocket 通信方式存在大量的辅助性的工作需要处理,例如心跳机制、粘包处理、协议规范等,所以直接使用 websocket 开发,等于重复造轮子,毫无价值,而 socket.io 整理了一整套规范和机制,可以满…

DSP-频域中的离散时间信号

目录 连续和离散时间傅里叶变换: 四种常用的傅立叶变换: 连续时间傅立叶变换(FT): 离散时间傅里叶变换(DTFT): 对称关系: DTFT的收敛条件: 常用DTFT对: DTFT的性质: 线性: 时间反转: 时移: 频移&#xff1a…

鲁大师2022牛角尖颁奖盛典落幕,各大硬件厂商齐聚襄阳

1月4日,鲁大师2022年度牛角尖颁奖晚会在湖北襄阳成功举办。 鲁大师的”牛角尖”奖是由过去一年上亿用户通过鲁大师测试得到的真实数据,以及鲁大师实验室通过专业的测试规范共同缔造的硬件奖项。颁发给的都是各大PC、手机、电动车领域最优秀、最顶尖的产…

【自学Python】Python HelloWorld

Windows Python HelloWorld Windows Python HelloWorld 教程 使用记事本,新建一个 helloworld.py 文件,输入以下内容: print(嗨客网(www.haicoder.net))打开命令行,进入到 helloworld.py 文件所在目录,输入以下命令…

干货 | 移动端App自动化之App控件定位

客户端的页面通过 XML 来实现 UI 的布局,页面的 UI 布局作为一个树形结构,而树叶被定义为节点。这里的节点也就对应了我们要定位的元素,节点的上级节点,定义了元素的布局结构。在 XML 布局中可以使用 XPath 进行节点的定位。App的…