【Golang】GC探秘/写屏障是什么?

之前写了 一篇【Golang】内存管理 ,有了很多的阅读量,那么我就接着分享一下Golang的GC相关的学习。

由于Golang的GC机制一直在持续迭代,本文叙述的主要是Go1.9版本及以后的GC机制,该版本中Golang引入了 混合写屏障大幅度地优化了STW的时间。具体GC机制的版本迭代可以参考 :GC的过去、现在和未来

基本概念

GC的对象

不再被需要的内存块,如果无法回收这部分内存将无法重复使用

内存泄漏

不再被需要的内存块,未在预期时间以内被回收的称为内存泄漏

常见的GC方法:

1.【PHP,Swift,Python等】引用计数法:

  • 每个对象维护一个自身被引用的次数,当一个引用者消息后该计数-1;
  • 它的优势为GC时查找需要回收的对象很简单:只需要找到引用计数为0的对象即可;
  • 它的劣势为在写入引用关系时需要额外维护引用计数,带来一定开销 ;
    2.【Golang】标记清除法:
  • 每次GC时通过从根对象出发递归地查询所有对象的引用关系,将无引用的对象进行标记后再行清理。
  • 它的优势在于写入引用关系时无额外开销
  • 它的劣势在于GC时查询引用关系有一定开销 ,有时还需要STW从而影响性能
STW: Stop the world

为了避免在GC的过程中,对象之间的引用关系发生新的变更使得GC的结果发生错误(比如GC过程中新增了一个引用,但是由于未扫描到该引用导致将被引用的对象清除了),停止所有正在运行的协程。
STW对性能有一些影响,Golang目前已经可以做到1ms以下的STW。

三色标记法

Golang中的GC方式为标记后清除,所采用的逻辑为——三色标记法:一开始全部的对象都是白色的


三色标记法
  1. 从root对象开始(全局变量+全局栈+当前活跃的goroutines中的栈),将它们加入到灰色队列中,进行遍历:类似于二叉树使用队列进行BFS遍历的过程
  2. 从灰色队列中pop出一个对象
  3. 将其引用的对象都置为灰色,加入到灰色队列中
  4. 将该对象置为黑色
  5. 直到灰色队列为空时,剩余的无引用的白色对象即会被清除

内存回收

看不太明白的可以参考我的上一篇文章:【Golang】内存管理

  1. 被回收的内存块会被回收到MCache(Processor私有内存)结构中 ,对应的MSpan(块类型)的allocBits的bitmap中对应的位置会被从1改为 0
  2. MSpan中除了allocBits还有另一个bitmap:GCMarkBits用于存放需要清除的标记:黑色=1,白色=0,一次GC之后所有MSpan中的GCMarkBits和AllocBits应该完全相同,因为只有黑色的内存对象在GC之后才会保留下来

写屏障

上文有提到为了避免GC的过程中新修改的引用关系到GC的结果发生错误,我们需要进行STW。但是STW会影响程序的性能,所以我们要通过写屏障技术尽可能地缩短STW的时间。

造成引用对象丢失的条件
  1. 一个黑色的节点A新增了指向白色节点C的引用
  2. 并且白色节点C没有除了A之外的其他灰色节点的引用,或者存在但是在GC过程中被删除了

以上两个条件需要同时满足:满足条件1时说明节点A已扫描完毕,A指向C的引用无法再被扫描到;满足条件2时说明白色节点C无其他灰色节点的引用了,即扫描结束后会被忽略 。

写屏障破坏两个条件其一即可
  1. 破坏条件1 => Dijistra写屏障
  • 满足强三色不变性:黑色节点不允许引用白色节点
  • 当黑色节点新增了白色节点的引用时,将对应的白色节点改为灰色
  1. 破坏条件2 => Yuasa写屏障
  • 满足弱三色不变性:黑色节点允许引用白色节点,但是该白色节点有其他灰色节点间接的引用(确保不会被遗漏)
  • 当白色节点被删除了一个引用时,悲观地认为它一定会被一个黑色节点新增引用,所以将它置为灰色
写屏障的分类

注意:由于栈上的操作需要保证性能,所以所有的写屏障均只针对堆上的对象。

写屏障的分类

GC的时机

  1. 每次内存分配时检查当前内存分配量是否已达到阈值(环境变量GOGC):默认100%,即当内存扩大一倍时启用GC
  2. 定时触发:当最近2分钟未触发过GC时,会触发一次GC
  3. 通过runtime.GC()手动触发

GC的优化

分配的对象越多,GC性能就越差,所以需要减少对象分配的个数,比如对象复用,使用sync.Pool

注意:sync.Pool类似于缓存,其中的对象会被定期清理(GC时清理),不能放置像是数据库连接这样需要稳定存储的数据

参考

1.三色标记法是什么?
2.Go语言垃圾收集器原理

最后编辑于:2025-02-05 20:55:05


喜欢的朋友记得点赞、收藏、关注哦!!!

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

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

相关文章

docker 运行 芋道微服务

jar包打包命令 mvn clean install package -Dmaven.test.skiptrue创建文件夹 docker-ai 文件夹下放入需要jar包的文件夹及 docker-compose.yml 文件 docker-compose.yml 内容:我这里的是ai服务,所以将原先的文件内容做了变更,你们需要用到什…

【苍穹外卖】学习

软件开发整体介绍 作为一名软件开发工程师,我们需要了解在软件开发过程中的开发流程, 以及软件开发过程中涉及到的岗位角色,角色的分工、职责, 并了解软件开发中涉及到的三种软件环境。那么这一小节,我们将从 软件开发流程、角色…

网工项目理论1.7 设备选型

本专栏持续更新,整一个专栏为一个大型复杂网络工程项目。阅读本文章之前务必先看《本专栏必读》。 一.交换机选型要点 制式:盒式交换机/框式交换机。功能:二层交换机/三层交换机。端口密度:每交换机可以提供的端口数量。端口速率:百兆/千兆/万兆。交换容量:交换矩阵…

前端面试技巧与实践

在当今快速发展的互联网行业中,前端开发已经成为了一个至关重要的角色。随着技术的不断进步和用户需求的日益复杂,前端工程师的职责不再仅仅是实现页面的布局和交互,而是需要具备全方位的技术能力和工程思维。根据2023年Stack Overflow的开发…

项目2 数据可视化--- 第十五章 生成数据

数据分析是使用代码来探索数据内的规律和关联。 数据可视化是通过可视化表示来 探索和呈现数据集内的规律。 好的数据可视化,可以发现数据集中未知的规律和意义。 一个流行的工具是Matplotlib,他是一个数据绘图库; 还有Plotly包&#xff…

前端常见面试题-2025

vue4.0 Vue.js 4.0 是在 2021 年 9 月发布。Vue.js 4.0 是 Vue.js 的一个重要版本,引入了许多新特性和改进,旨在提升开发者的体验和性能。以下是一些关键的更新和新特性: Composition API 重构:Vue 3 引入了 Composition API 作为…

python学opencv|读取图像(六十八)使用cv2.Canny()函数实现图像边缘检测

【1】引言 前序学习进程中,在对图像进行边缘识别的基础上,先后进行了边缘轮廓绘制,矩形标注、圆形标注和凸包标注。相关文章包括且不限于: python学opencv|读取图像(六十四)使用cv2.findContours()函数cv…

C语言基础16:二维数组、字符数组

二维数组 定义 二维数组本质上是一个行列式的组合,也就是说二维数组由行和列两部分组成。属于多维数组,二维数组数据是通过行列进行解读。 二维数组可被视为一个特殊的一维数组,相当于二维数组又是一个一维数组,只不过它的元素…

小爱音箱连接电脑外放之后,浏览器网页视频暂停播放后,音箱整体没声音问题解决

背景 22年买的小爱音箱增强版play,小爱音箱连接电脑外放之后,浏览器网页视频暂停播放后,音箱整体没声音(一边打着游戏,一边听歌,一边放视频,视频一暂停,什么声音都没了,…

【做一个微信小程序】校园地图页面实现

前言 上一个教程我们实现了小程序的一些的功能,有背景渐变色,发布功能有的呢,已支持图片上传功能,表情和投票功能开发中(请期待)。下面是一个更高级的微信小程序实现,包含以下功能:…

使用Navicat for MySQL工具连接本地虚拟机上的MySQL

昨天在虚拟机上装了MySQL数据库,今天打算用Navicat for MySQL工具连下,结果连接不上。 使用本地Navicat for MySQL工具连接虚拟机上的MySQL数据库: 1.Navicat连接mysql 解决方案 1、首先使用xshell工具连上虚拟机服务器,输入命令&…

算法笔记 02 —— 入门模拟

本系列为胡凡编著的算法笔记当中代码部分的精简版整理,笔者也在同时准备Leetcode刷题和实习面试,希望为有一定编码和数据结构基础的同学提供一份系统型的参考,以方便遗忘时的算法查阅、期末复习总览以及C学习参照。 目录 01 简单模拟 Ⅰ害…

unity学习38:导入角色和动画,实测用脚本控制trigger和动作状态的转换

目录 1 资源准备:先从unity的 Asset store下载一些free的资源 2 在project/Asset里找到角色模型和动画 2.1 在prefab里找到角色资源 2.2 找到动画资源,一般在Animation下的模型文件fbx下层 2.3 准备工作 2.4 拖拽模型文件里的动作到Animator 2.5 …

Weboffice在线Word权限控制:限制编辑,只读、修订、禁止复制等

在现代企业办公中,文档编辑是一项常见且重要的任务。尤其是在线办公环境中,员工需要在网页中打开和编辑文档,但如何确保这些文档只能进行预览而无法被编辑或复制,成为许多企业面临的一个痛点。尤其是在处理涉密文档时,…

Endnote使用笔记——持续更新

(1)如果样式库里没有想要的期刊格式,可以到这个网址进行下载,并放在本地安装Endnote的文件下边的styles文件里: https://endnote.com/downloads/styles/ (2)EndNote导入参考文献时,关…

try learning-git-branching

文章目录 mergerebase分离 HEAD相对引用利用父节点branch -f 撤销变更cherry-pick交互式 rebase只取一个提交记录提交的技巧rebase 在上一次提交上amendcherry-pick 在上一次提交上 amend tag多分支 rebase两个parent节点纠缠不清的分支偏离的提交历史锁定的Main推送主分支合并…

Unity使用反射进行Protobuf(CS/SC)协议,json格式

protobuf生成的协议,有挺多协议的.利用反射生成dto进行伪协议的响应 和 发送请求 应用场景: 请求(CS)_后端先写完了(有proto接口了),前端还没搞完时(暂还没接入proto),后端可使用此请求,可自测 响应(SC)_可自行构建一个响应(有些特殊数据后端下发不了的),对数据进行测试 // 请…

Linux探秘坊-------8.进程详解

1.概念详解 1.运行&&阻塞&&挂起 内容基础:方框中的就是调度队列,是一个 双向队列,每一个元素是PCB其对应的代码数据 1.运行 只要进程 在调度队列中,进程的状态就是运行(running). 2.阻塞…

VUE 集成高德地图部署到nginx后打开不了,控制台报错

VUE 集成高德地图部署到nginx后打开不了,控制台报错:xxxxxxx,because it violates the following Content Security Policy directive: “script-src ‘self’ https://webapi.amap.com ‘unsafe-inline’ ‘unsafe-eval’ blob: data:”. Note that ‘script-src-e…

解决vue-awesome-swiper 4.x + swiper 5.x 分页pagination配置不生效问题

这次给的需求需要实现几个轮播图,我打算用swiper来做。刚开始我参照同事之前实现的swiper,复制到我的新页面中,是可用的。但是这次的需求需要有底下的分页pagination,而且因为版本比较老,比较难找到配置项。这里说一下…