序言

 垃圾回收(Garbage Collection,简称 GC)机制 是一种自动内存管理技术,主要用于在程序运行时自动识别并释放不再使用的内存空间,防止内存泄漏和不必要的资源浪费。这篇文章让我们来看一下 Go 语言的垃圾回收机制是如何设计的吧。


一、为什么需要垃圾回收?

 熟悉 C/C++ 编程的同学肯定清楚自己手动管理内存的手段:

  • 分配内存:malloc, new
  • 释放内存:free, delete

对待内存管理一定要小心谨慎,不然稍有疏漏就会引起以下严重的问题:

  • 忘记释放内存 → 内存泄漏
  • 多次释放同一块内存 → 崩溃或未定义行为
  • 访问已释放的内存 → 悬空指针

所以说垃圾回收机制大大的提高了内存管理的下限,但是同时这是以一定的性能开销换取的。


二、Go 垃圾回收机制

 我们现在看到的机制都是比较完善的,但是很多时候我们不明白他为什么要这么做,有什么好处?这是因为我们站在巨人的肩膀上,机制是在使用中不断完善的。所以看事情不能只看现在,明白他大致来时候的路是必要的。

2.1 标记-清扫式垃圾回收(Mark-Sweep GC)

2.1.1 回收流程

 首先当前执行的逻辑暂停(也称为 Stop-The-World STW),然后标记所有存活对象。从根对象(比如全局变量、当前栈中的局部变量等)开始遍历所有被引用的对象,并将对象标记为存活状态:
在这里插入图片描述
现在标记的动作完成了,需要回收没有被引用的空间了。遍历整个堆的空间,然后对于没有被标记的对象,释放其内存:
在这里插入图片描述
最后便是恢复程序的执行了,可以看出刚开始的机制还是比较简单的。

2.1.2 Mark-Sweep 的缺点

STW 时间长降低了程序的执行的效率。如果当前的程序对于空间的申请和释放的操作比较频繁时,执行时的卡顿感会愈发的强烈,因为 STW 这段时间程序是被阻塞的,无法正常运行。
 内存碎片化严重。清扫后会产生很多小块的空闲内存,可能导致大对象无法分配,降低了内存的利用率。
 扫描整个堆。如果当前堆比较大的话,也会拉长 STW 的时间。

这个方式是在 Go V1.4 之前使用的,现在被替换了,但是作为一个引子还是不错的。

2.2 三色并发垃圾回收(Tri-color Concurrent GC )

2.2.1 回收流程

 首先在每次创建新的对象的时候将该对象标记为 白色
在这里插入图片描述
现在触发 GC 了,从根节点遍历,将该节点 root 指向的堆对象从 white 表 放入 grey 表,由于这里只有一个根对象,所以这里只需要处理 a
在这里插入图片描述
根上的对象遍历完成了,现在遍历 grey 表 将节点 a 指向的对象也全放入 grey 表 ,同时将 a 放入 black 表 表示他的可达对象处理完成了:在这里插入图片描述
之后重复第二部操作直至 grey 表 的数据为空:
在这里插入图片描述
到最后我们发现 white 表 只剩下了一个不可达对象 f,这个就是需要回收的空间。纵观整个过程,其实就是一个广度遍历来查找不可达对象的过程。
 比较现有的两个机制,后者一个很大优点就是 不需要遍历整个堆来查找不可达对象,因为最开始的时候就记录了创建的每一个对象。但是我们这里好像少了些什么,不需要 STW 吗?

2.2.2 假设没有 STW

 就比如 e 其实是一个可达对象的,但是由于在执行回收的过程中当前的程序也在正常的执行,让 de 断开连接并让一个新的根节点(比如局部变量)指向 e
在这里插入图片描述
因为对根节点的遍历只在最初执行一遍,后续不会再遍历了导致错误地判定 e 为不可达对象释放该空间,这不就错误地释放空间了吗(也称为 漏标)。
 最直接的方式就是在回收的过程中加上 STW,但是这个方式的弊端上面也说过了。那怎么办呢?减少 STW 的时间。

2.2.3 屏障机制
1. 强弱三色不变式

 由于程序的执行和垃圾回收的过程是并发的,就导致了错误地回收了某些还需要继续使用的对象。为了避免这种情况,引入了 三色不变式
强三色不变式,所有黑对象不能直接或间接引用白对象。也就是说:如果一个对象已经是黑色,它不能指向任何未被标记的白色对象。
弱色不变式。所有白对象可以被黑色对象引用,但是这个白色对象必须存在着其他灰色对象对他的引用。

2. 插入写屏障

满足:强三色不变式
操作:当一个黑色对象引用一个白色对象之前,先将该白色对象修改为灰色对象,在建立引用:
在这里插入图片描述
并且这里还有一个机制是 插入写屏障只作用于堆对象。因为栈上的变量变更比较频繁, 如果一变更我们就去执行插入写屏障会非常的耽误时间。作为补偿,会在整体三色标记清除之后,专门对栈上的空间执行次三色标记扫描并加上 STW 保护。

3. 删除写屏障

满足:弱三色不变式
操作:当一个白色对象被上游删除引用时,会将将自己修改为灰色对象:
在这里插入图片描述
这种方式其实也是延迟回收策略,当真正想删除该对象时,这一轮他会存活下来,但是下一轮肯定会被带走。

2.3.4 Tri-color Concurrent 的缺点

 这两种方式任选一种即可解决漏标的问题,Go V1.8 及以前使用的是删除写屏障。该种方式的缺点是:

  • 回收精度偏低。本次 GC 过程中需要删除的对象会在下一轮清除

而插入写屏障的缺点也不小:

  • 会在结束时扫描整个栈,并且伴随着 STW

那是否可以取长补短互相融合呢?

2.3 混合写屏障机制(Hybrid Write Barrier)

 将栈上的对象扫描之后全部标记为 黑色,期间任何新增的对象标记为 灰色,任何被删除的对象也标记为 灰色。这样节省了扫描整个栈并伴随的 STW 带来的性能消耗。


三、总结

 现在纵观大体的发展路线,你是否可以理解:混合写屏障(Hybrid Write Barrier)是一种改进型写屏障机制,它结合了 删除写屏障 和 插入写屏障 的优点,在并发三色标记中有效地防止漏标问题,并显著减少了 STW 时间。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

60天python训练计划----day45

DAY 45 Tensorboard使用介绍 知识点回顾: tensorboard的发展历史和原理tensorboard的常见操作tensorboard在cifar上的实战:MLP和CNN模型 之前的内容中,我们在神经网络训练中,为了帮助自己理解,借用了很多的组件&#x…

RocketMQ基础概念的理解

1、生产者 生产者和主题之间存在多对多关系。一个生产者可以向多个主题发送消息,一个主题可以接收来自多个生产者的消息。这种多对多关系有助于提高性能扩展和灾难恢复能力。 2、消费者以及消费者组 一个队列可以被多个消费者(其中这多个消费者必须分…

Flash烧录速度和加载配置速度(纯FPGA ZYNQ)

在工程综合完成或者implement完成后,打开综合设计或者实现设计。 toots--->Edit Device Properties--->打开比特流设置 将bitstream进行压缩 上图中,时钟频率选择的档位有限,最大为66MHZ io的bus width可以设置为x1,x2,x4 vivado在设计…

优化09-表连接

一、表连接介绍 表连接类型 表连接是关系型数据库关键特性,在关系型数据库中,表连接分为三类:循环嵌套连接(Nested Loops Join)、哈希连接(Hash Join)、合并排序连接(Merge Sort J…

Dify工作流实践—根据word需求文档编写测试用例到Excel中

前言 这篇文章依赖到的操作可查阅我之前的文章: dify里的大模型是怎么添加进来的:在Windows本地部署Dify详细操作 flask 框架app.route()函数的开发和调用:PythonWeb开发框架—Flask工程创建和app.route使用详解 结构化提示词的编写&…

AWTK 嵌入式Linux平台实现多点触控缩放旋转以及触点丢点问题解决

前言 最近涉及海图的功能交互,多点触摸又开始找麻烦。 在PC/Web平台awtk是通过底层的sdl2库来实现多点触摸,但是在嵌入式Linux平台,可能是考虑到性能原因,awtk并没有采用sdl库来做事件处理,而是自己实现一个awtk-lin…

Diffusion Planner:扩散模型重塑自动驾驶路径规划(ICLR‘25)

1. 概述 2025年2月14日,清华大学AIR智能产业研究院联合毫末智行、中科院自动化所和香港中文大学团队,在ICLR 2025会议上发布了Diffusion Planner——一种创新性的基于Diffusion Transformer的自动驾驶规划模型架构。该系统联合建模周车运动预测与自车行…

ESP32对接巴法云实现配网

目录 序言准备工作巴法云注册与使用Arduino准备 开发开始配网 序言 本文部分内容摘抄原创作者巴法云-做优秀的物联网平台 代码有部分修改并测试运行正常 巴法云支持免费用户通过开发对接实现各智能音箱设备语音控制智能家居设备,并有自己的App进行配网和控制&…

深度学习习题3

1.训练神经网络过程中,损失函数在一些时期(Epoch)不再减小, 原因可能是: 1.学习率太低 2.正则参数太大 3.卡在了局部最小值 A1 and 2 B. 2 and 3 C. 1 and 3 D. 都是 2.对于分类任务,我们不是将神经网络中的随机权重…

【EasyExcel】导出时添加页眉页脚

一、需求 使用 EasyExcel 导出时添加页眉页脚 二、添加页眉页脚的方法 通过配置WriteSheet或WriteTable对象来添加页眉和页脚。以下是具体实现步骤: 1. 创建自定义页眉页脚实现类 public class CustomFooterHandler implements SheetWriteHandler {private final…

c++ 类型转换函数

测试代码&#xff1a; void testTypeTransfer() { // 测试类型转换函数class Distance {private:int meters;public:// 类型转换函数&#xff0c;int表示转化为int类型operator int() {std::cout << "调用了类型转换函数" << endl;return meters; }Dist…

Conda 基本使用命令大全

Conda 基本使用命令大全 Conda 是一个开源的包管理和环境管理系统&#xff0c;广泛用于 Python 开发、数据科学和机器学习。以下是 最常用的 Conda 命令&#xff0c;涵盖环境管理、包安装、配置等核心操作。 1. 环境管理 创建环境 conda create --name myenv # 创…

基于SpringBoot和PostGIS的OSM时空路网数据入库实践

目录 前言 一、空间表的设计 1、属性信息 2、空间表结构设计 二、路网数据入库 1、实体类设计 2、路网数据写入 3、pgAdmin数据查询 三、总结 前言 在当今数字化时代&#xff0c;随着信息技术的飞速发展&#xff0c;地理空间数据的应用范围越来越广泛&#xff0c;尤其是…

代付入账是什么意思?怎么操作?

代付入账就是指商户委托银行通过企业银行账户向指定持卡人账户划付款项&#xff0c;款项划入指定账户即为入账。 具体操作流程如下&#xff1a; 1. 向第三方支付公司指定账户充值加款。 2. 通过操作后台提交代付银行卡信息。 3. 第三方支付公司受理业务申请。 4. 第三方审…

数学复习笔记 27

前言 太难受了。因为一些事情。和朋友倾诉了一下&#xff0c;也没啥用&#xff0c;几年之后不知道自己再想到的时候&#xff0c;会怎么考虑呢。另外&#xff0c;笔记还是有框架一点比较好&#xff0c;这样比较有逻辑感受。不然太乱了。这篇笔记是关于线代第五章&#xff0c;特…

第四十五天打卡

知识点回顾&#xff1a; tensorboard的发展历史和原理 tensorboard的常见操作 tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很适合拿去组会汇报撑页数&#xff1a; 作业&#xff1a;对resnet18在cifar10上采用微调策略下&#xff0c;用tensor…

使用高斯朴素贝叶斯算法对鸢尾花数据集进行分类

高斯朴素贝叶斯算法通常用于特征变量是连续变量&#xff0c;符合高素分布的情况。 使用高斯朴素贝叶斯算法对鸢尾花数据集进行分类 """ 使用高斯贝叶斯堆鸢尾花进行分类 """ #导入需要的库 from sklearn.datasets import load_iris from skle…

【docker】Windows安装docker

环境及工具&#xff08;点击下载&#xff09; Docker Desktop Installer.exe &#xff08;windows 环境下运行docker的一款产品&#xff09; wsl_update_x64 &#xff08;Linux 内核包&#xff09; 前期准备 系统要求2&#xff1a; Windows 11&#xff1a;64 位系统&am…

量化Quantization初步之--带量化(QAT)的XOR异或pyTorch版250501

量化(Quantization)这词儿听着玄&#xff0c;经常和量化交易Quantitative Trading (量化交易)混淆。 其实机器学习(深度学习)领域的量化Quantization是和节约内存、提高运算效率相关的概念&#xff08;因大模型的普及&#xff0c;这个量化问题尤为迫切&#xff09;。 揭秘机器…

【Redis】zset 类型

zset 一. zset 类型介绍二. zset 命令zaddzcard、zcountzrange、zrevrange、zrangebyscorezpopmax、zpopminzrank、zrevrank、zscorezrem、zremrangebyrank、zremrangebyscorezincrby阻塞版本命令&#xff1a;bzpopmax、bzpopmin集合间操作&#xff1a;zinterstore、zunionstor…