Golang中GC和三色屏障机制【Golang面试必考】
文章目录
- Go v1.3 标记—清楚(mark and sweep)方法
- Go V1.5 三色标记法
- 三色标记过程无STW的问题
- 强弱三色不变式
- 插入写屏障
- Go V1.8的三色标记法+混合写屏障机制
- 混合写屏障场景
- 场景1:对象被一个堆对象删除引用,成为栈对象的下游
- 场景2:对象被一个栈对象删除引用,成为另一个新建栈对象的下游
- 场景3:对象被一个堆对象删除引用,成为另一个堆对象的下游
- 场景4:对象从一个栈对象删除引用,成为另一个堆对象的下游
- 总结
Go v1.3 标记—清楚(mark and sweep)方法
-
主要流程
- 暂停程序业务逻辑,找出可达对象和不可达对象;
- 开始标记,程序找出它所有可达的对象,并做上标记;
- 标记完了之后,然后开始清除未标记的对象;
- 停止暂停,让程序继续跑,然后循环重复这个过程,直到process程序声明周期结束;
-
标记清除整体逻辑

-
标记清除的缺点
- STW,stop the world ;让程序暂停,程序出现卡顿
- 标记需要扫描整个heap;
- 清楚数据会产生heap碎片;【如果地址不连续】
其中最大的问题还是因为STW太费时间,早期的探索是通过将sweep阶段移到STW之外,这确实是一种改善的方法,但是始终难以改变这种低级效能。所以需要尝试采用新的标记模式来代替清楚标记法(mark-sweep)—三色标记法。

Go V1.5 三色标记法
- 主要流程


主要的流程如下【广度优先搜索】:
- 只要是新创建的对象,默认的颜色都是标记为"白色";
- 每次GC回收开始,然后从根节点开始遍历所有对象,把遍历到的对象从白色集合中放入"灰色"集合中;
- 遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将原先的灰色对象放入黑色集合当中;
- 重复第三步,直到灰色中无任何对象;
- 回收所有白色标记表的对象,也就是回收垃圾;
三色标记过程无STW的问题
- 如果三色标记中不启动STW会怎么样?

简单来说,就是没有STW,那么如果对象2对对象3依赖的指针取消了,而对象四新建了一个对对象3的依赖,那么按照之前的原则,每次都是对灰色节点进行遍历,所以这个时候,无法将对象3标记为灰色,故会造成错误。
-
三色标记最不希望发生的事情
- 条件1:一个白色对象被黑色对象引用(白色挂在黑色下)
- 条件2:灰色对象与它之间的可达关系的白色对象遭到破坏(灰色同时丢了该白色)
以上两个条件同时满足就会发生对象的丢失。因此有必要使用STW,但是应当尽可能的提高GC效率,减少STW时间。

强弱三色不变式
-
强三色不变式
强制性的不允许黑色对象引用白色对象。
-
弱三色不变式
黑色对象可以引用白色对象,但是白色对象存在其他灰色对象对它的引用,或者可达它的链路上游存在灰色对象。
在三色标记中如果满足强/弱之一,即可保证对象不丢失。为了使用上面这种思想,引入了屏障。
插入写屏障
-
屏障的理解

-
屏障机制
-
插入屏障:对象被引用的时候触发的机制
在A对象引用B对象的时候,B对象被标记为灰色(将B挂在A下游,B必须被标记为灰色)【强三色不变式】
// 伪码 添加下游对象(当前下游对象slot,新下游对象ptr){// 1标记灰色(新下游对象)// 2当前下游对象slot = 新下游对象ptr }⭐️⭐️⭐️一般为了保证效率,不会在栈上使用插入屏障。【栈不触发插入屏障,是因为栈上的内存会随着栈销毁而回收,除非触发内存逃逸】
-

也就是说在堆上的对象才会启用插入屏障。在准备回收白色前,重新遍历扫描一边栈空间,此时加STW暂停保护栈,防止有外界干扰(有新的白色被黑色添加)

插入写屏障的不足就是在结束时需要用STW来重新扫描栈,大约需要10ms~100ms
-
删除屏障:当引用关系被删除的时候触发的机制
具体操作:被删除的对象,如果自身或者上游对象为灰色或者白色,那么被标记为灰色【满足弱三色不变式,保护灰色对象到白色对象的路径不会断】
// 伪代码 添加下游对象(当前下游对象slot,新下游对象ptr) 「 // 1 if (当前下游对象slot是灰色 || 当前下游对象slot是白色) {标记灰色(新下游对象ptr) } // 2 当前下游对象slot = 新下游对象ptr删除写屏障的不足之处在于回收精度低,一个对象及时被删除了最后一个指向它的指针也依旧可以活过这一轮,在下一轮GC中被清理掉。
Go V1.8的三色标记法+混合写屏障机制
-
具体操作
- GC开始将栈上的对象全部扫描并标记为黑色(之后不在进行第二次重复扫描,无需STW)
- GC期间,任何在栈上创建的新对象,均为黑色
- 被删除的对象标记为灰色
- 被添加的对象标记为灰色
变形的弱三色不变式(结合插入、删除写屏障两者的优点)
//伪码 添加下游对象(当前下游对象slot,新下游对象ptr){// 1标记灰色(当前下游对象slot)// 2标记灰色(新下游对象)// 3当前下游对象slot = 新下游对象ptr }
混合写屏障场景
场景1:对象被一个堆对象删除引用,成为栈对象的下游
// 伪代码
// 前提:堆对象->对象7 = 对象7;// 对象7 被 对象4 引用
栈对象1->对象7 = 堆对象7;// 将堆对象7挂载在 栈对象 下游
堆对象4->对象7 = null;//对象4 删除引用 对象7
对象4删除了对象7的引用关系,因为对象4是堆区,所以触发删除屏障,标记被删除的对象7为灰。【注意这个地方不能认为栈里面元素添加一个就直接标记为黑色,因为栈的区域不启用屏障】
场景2:对象被一个栈对象删除引用,成为另一个新建栈对象的下游
(1)、新创建一个对象9在栈上(因为是混合写屏障模式中,GC过程汇总任何在栈中新创建的对象均标记为黑色)
(2)、对象9添加下游引用栈堆对象3(直接添加,栈不启动屏障,无屏障效果)
(3)、对象2删除对象3的引用关系(直接删除,栈不启动写屏障,无屏障效果)
场景3:对象被一个堆对象删除引用,成为另一个堆对象的下游
//伪代码
堆对象10 -> 对象7 = 堆对象7; // 将堆对象7 挂在 堆对象10 下游
堆对象4 -> 对象7 = null; // 对象4 删除引用 对象7
(1)、堆对象10已经扫描标记为黑(黑色情况比较特殊,其他颜色暂不考虑)。
(2)、堆对象10添加下游引用堆对象7,触发屏障机制,被添加的对象标记为灰色,对象7变成灰色(对象6被保护)。
(3)、堆对象删除下游引用堆对象7,触发屏障机制,被删除的对象标记为灰色,对象7被标记为灰色。
场景4:对象从一个栈对象删除引用,成为另一个堆对象的下游
// 伪代码
栈对象1 -> 对象2 = null; // 对象1 删除引用 对象2
栈对象4 -> 对象2 = 栈对象2 // 对象4 添加栈对象2
堆对象 -> 对象7 = null; // 对象4 删除一个对象7
(1)、栈对象1删除对堆对象2的引用。(栈空间不触发写屏障)。
(2)、堆对象将之前引用对象7的关系,转移至对象2(对象4删除对象7的引用关系)。
(3)、对象4在删除的时候,触发写屏障,标记被删除对象7为灰色。保护对象7及其下游节点。
总结
Go V1.3 使用普通标记清除法,整体过程需要STW,效率极其低
Go V1.5 三色标记法,堆空间启动写屏障,栈空间不启动,全部扫描一次后,需要重新扫描一次栈(需要STW),效率极其普通
Go V1.8 三色标记法+混合写屏障机制,堆空间启动,栈空间不启动,整体过程几乎不需要STW,效率较高
相关文章:
Golang中GC和三色屏障机制【Golang面试必考】
文章目录Go v1.3 标记—清楚(mark and sweep)方法Go V1.5 三色标记法三色标记过程无STW的问题强弱三色不变式插入写屏障Go V1.8的三色标记法混合写屏障机制混合写屏障场景场景1:对象被一个堆对象删除引用,成为栈对象的下游场景2:对象被一个栈对象删除引用࿰…...
MOS FET继电器(无机械触点继电器)设计输入侧电源时的电流值概念
设计输入侧电源时的问题 机械式继电器、MOS FET继电器分别具有不同的特长。基于对MOS FET继电器所具小型及长寿命、静音动作等优势的需求,目前已经出现了所用机械式继电器向MOS FET继电器转化的趋势。 但是,由于机械式继电器与MOS FET继电器在产品结构…...
5. 驱动开发
文章目录一、驱动开发1.1 前言1.2 何谓驱动框架1.3 内核驱动框架中LED的基本情况1.3.1 相关文件1.3.2 九鼎移植的内核中led驱动1.3.3 案例分析驱动框架的使用1.3.4 典型的驱动开发行业现状1.4 初步分析led驱动框架源码1.4.1 涉及到的文件1.4.2 subsys_initcall1.4.3 led_class_…...
模板方法模式详解
模板方法模式(行为模式) 1. 模板方法模式介绍 父类定义算法骨架,细节的具体实现延迟到子类子类只是定义某些自己的个性化处理,但不改变执行顺序 2. 好处 减少代码冗余,共性抽取后算法流程更加清晰与规范降低流程性…...
关于 Lightweight process container,ChatGPT的答案
晓楚 Can you give me a list of process container? As an AI language model, I can provide you with a list of popular process containers, which are as follows: Docker Kubernetes Apache Mesos LXC OpenVZ systemd-nspawn rkt (Rocket) Linux Containers (LXC) Ga…...
机器学习和深度学习的综述
机器学习和深度学习的综述 1.1.1人工智能、机器学习、深度学习的关系 人工智能(Artificial Intelligence,AI)是最宽泛的概念,是研发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。由于这个定义…...
Synopsys Sentaurus TCAD系列教程之--Sprocess(SmallMOS_2D3D) 解析
SmallMOS_2D3D解析 #header## STI depth set sti_depth 0.15 ## Half STI width set sti_width sti_width ## Half gate length set gate_len <lg/2> ## SD length (from center) set sd_len [expr $gate_len0.05]#endheader## X lines line x location 0.0 spacing 0.…...
好使!NAS中傻瓜式配置反向代理及SSL证书,提升网络安全性!
对于有NAS或者有个人主机的朋友来说,将机器映射到外网是基本操作。 但是一般来说,能直接从外网访问的往往仅有80和443端口。事实上,运营商一般把家庭宽带的这两个端口都封了,所以如果我们想要从外网访问自己家中机器部署的服务&a…...
数据结构队列-先进先出
一,概述 队列这个概念非常好理解。你可以把它想象成排队买票,先来的先买,后来的人只能站末尾,不允许插队。先进者先出,这就是典型的“队列”。 二,顺序队列和链式队列 队列和栈一样,也是一种…...
CentOS 7使用TiUP部署TiDB
本文主要是根据官方文档指导,结合实际主机情况,在Cent OS7上使用TiUP在线部署TiDB。 环境说明 类型操作系统版本配置中控机Deepin 20.34核CPU6G内存40G硬盘TiDB部署机Cent OS 7.38核CPU48G内存100硬盘网络情况中控机与外网相连,中控机与部署…...
java单元测试批处理数据模板【亿点点日志配合分页以及多线程处理】
文章目录引入相关资料环境准备分页查询处理,减少单次批量处理的数据量级补充亿点点日志,更易观察多线程优化查询_切数据版多线程_每个线程都分页处理引入 都说后端开发能顶半个运维,我们经常需要对大量输出进行需求调整,很多时候…...
【数据结构】模拟实现 堆
堆数据结构是一种数组对象,它可以被看作一颗完全二叉树的结构(数组是完全二叉树),堆是一种静态结构。堆分为最大堆和最小堆。最大堆:每个父结点都大于孩子结点。最小堆:每个父结点都小于孩子结点。堆的优势…...
Go语言学习的第三天--上部分(基础用法)
前两天经过不断度娘,与对up主的跟踪学习了解了go的历史,今天开始了go的基础!!本章主要是go 的注释、变量及常量的梳理一、注释不管什么语言都有自己的注释,go也不例外 !!单行注释 // 多行注释 …...
linux面试基础篇
题目目录1.简述DNS分离解析的工作原理,关键配置2.apache有几种工作模式,分别简述两种工作模式及其优缺点?3.写出172.0.0.38/27 的网络id与广播地址4.写出下列服务使用的传输层协议(TCP/UDP)及默认端口5.在局域网想获得…...
黑马程序员提高变成
这里写目录标题函数模板1.2.2 函数模板注意事项1.2.3 函数模板案例调用规则类模板与函数模板区别类模板与继承类模板成员函数类外实现#pragma once类模板与友元案例重新定义【】stl2.2 STL基本概念STL六大组件容器算法迭代器初识vectorvector容器嵌套容器string容器string赋值操…...
MySQL5种索引类型
MySQL的类型主要有五种:主键索引、唯一索引、普通索引、空间索引、全文索引 有表: CREATE TABLE t1 ( id bigint unsigned NOT NULL AUTO_INCREMENT, u1 int unsigned NOT NULL DEFAULT 0, u2 int unsigned NOT NULL DEFAULT 0, u3 varchar(20) NOT NU…...
uniapp封装缓存方法,支持类似cookie具有过期时间
1、定义CacheManage类,有set和get方法 class CacheManage {set() {},get() {} }set用来设置缓存,get用来获取缓存 2、完善set业务逻辑 大概逻辑如下: 1、将接收params参数,包含key、data、unit、time key 缓存字段,…...
Jfrog 搭建本地maven仓库以及上传Android库
Jfrog 下载 安装包下载地址:Download Artifactory OSS | JFrog 如果是想下载之前的版本,可以点击上面的Get code source ,如果是最新版本,直接点下面的下载就好。下面以Linux安装为例。 Jfrog安装 对于Linux而言,其实…...
日报周报月报工作总结生成器【智能文案生成器】
日报周报月报工作总结生成器【智能文案生成器】 天天写日报,我真的快奔溃了! 摸了一天鱼,下班还要写日报; 划了一周的水,周末还要写周报; 啊啊啊啊… 在职场上,尤其是互联网公司里,…...
linux日志管理工具logrotate配置
linux日志管理工具logrotate配置logrotate介绍logrotate配置讲解主配置文件解释(/etc/logrotate.conf)logrotete 命令参数添加配置以添加一个nginx配置为例强制启动配置logrotate介绍 logrotate是centos自带工具,其他操作系统可能需要自行安装。logrotate用来进行日…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
