Golang三色标记法

简介

在JVM中,GC采用可达性分析法来判断对象是否死亡;在python虚拟机中,GC采用引用计数法加循环检测器来判断对象是否死亡,而在golang中,使用的是三色表记法来判断对象是否死亡。

什么是三色抽象

总所周知在GC时,通常会出现 stop the world问题(即垃圾回收器抢占CPU资源导致程序暂停)。在golang中为了解决这个问题,我们引出了三色抽象法,至于如何解决接下来我们详细说说。

首先我们需要了解三色指的是哪三色,分别有什么含义:

  • 白色对象:潜在的垃圾,其内存可能会被垃圾收集器回收。
  • 黑色对象:活跃对象,包括不存在任何引用外部指针的对象,以及根对象可达的对象。
  • 灰色对象:活跃对象,因为存在指向白色对象的外部指针,所以垃圾收集器回扫描这些对象的子对象

看到这里大家可能会有一些疑惑:

  1. 黑色对象中的不存在任何引用外部指针的对象,以及根对象可达的对象,是什么意思?
  2. 为什么存在两种活跃对象?

问题1其实可以画图解释,由于三色标记法没有指明根对象,所以是和可达性分析法结合使用的。

途中三个个黑色对象就对应了不存在任何引用外部指针的对象,以及根对象可达的对象

而关于问题2,我们在接下来将会解答。

回收过程

首先我们需要了解有哪些对象在三色抽象中被视作根对象:

  1. 全局变量:这些是程序的全局状态,包括在函数外部声明的所有变量。

  2. 当前活动的 goroutine 栈:每个 goroutine 都有自己的栈,栈上的变量都被视为根对象。

  3. 其他运行时数据结构:这些包括一些内部的运行时数据结构,如 finalizer 队列。

在垃圾收集器刚刚开始工作时,所有的对象都为白色,不存在黑色对象。这时根对象被标记为灰色,垃圾收集器只会从灰色对象集合中取出对象开始扫描,当灰色对象集为空时,标记阶段就结束了。

屏障技术

在标记过程中,我们会遇到一个新的问题,由于多数现代处理器会乱序执行指令以达到性能最大化,导致的乱序问题。也可以理解为在并发场景下用户线程与gc线程同时进行,导致引用关系被改变。所以为了在并发、增量标记算法中保证标记正确性,不会出现类似于悬挂指针类似问题,我们就需要满足三色不变性:

  • 强三色不变性:
    • 黑色对象不会指向白色对象(在golang中体现为如果一个黑色对象引用一个新对象,该对象会被立即标记为灰色或黑色),只会指向灰色对象或者黑色对象。
  • 弱三色不变性:
    • 黑色对象指向白色对象必须包含一条灰色对象经由多个白色对象的可达路径。

只要满足上述两种三色不变性之一就符合要求。

屏障技术主流使用的有两种:插入写屏障和删除写屏障 (为什么没有读屏障呢?这时由于读屏障需要在用户程序使用时插入代码,对用户程序性能影响大)

  1. 插入写屏障(Insertion Write Barrier):在引用关系被修改之前插入一些额外的操作。例如,当一个对象 A 要引用另一个对象 B 时,插入写屏障会首先将 B 标记为可达,然后再修改 A 的引用。这样,即使在修改引用的过程中发生了垃圾回收,B 也不会被错误地回收。

  2. 删除写屏障(Deletion Write Barrier):在引用关系被修改之后插入一些额外的操作。例如,当一个对象 A 不再引用另一个对象 B 时,删除写屏障会在修改 A 的引用之后,检查 B 是否还被其他对象引用。如果 B 不再被任何对象引用,那么它就会被标记为垃圾。

增量和并发

屏障技术都是为了服务增量和并发场景下的gc,我们如此如此麻烦就是为了解决gc的STW问题。增量垃圾收集器会增量的标记和清除垃圾,降低应用程序暂停的最长时间。并发垃圾收集器利用多核的计算机资源在用户程序执行时并发标记与清除垃圾。

GC发生条件

STW的垃圾收集器能够有效控制堆大小。Golang默认配置会在堆内存达到上次垃圾收集的两倍时出发新的一轮垃圾收集。即默认值为100。

而并行垃圾收集其由于需要与程序一起运行,所以无法精确控制内存大小,在达到目标前就触发gc。

注意

在Golang和Java中都存在主动gc的指令,但是它们却有很大差异。在Java中存在 System.gc()命令,它会建议JVM开始进行gc,但是最终是否gc是取决于JVM的。但是在Gloang中,只要使用了runtime.GC指令,该方法就会在调用时阻塞调用方,直到当前垃圾收集循环完成。

垃圾回收过程(引子)

回收过程则是调用一系列函数对内存进行释放,这就涉及到Golang内存分配部分知识了。会遍历稀疏内存的runtime.mspan来检查每个内存页对象是否为白色对象,如果是就释放该部分内存。具体回收过程可能会在后续发布。

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

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

相关文章

分享:Javascript开源桌面环境-Puter

Puter这是一个运行在浏览器里的桌面操作系统,提供了笔记本、代码编辑器、终端、画图、相机、录音等应用和一些小游戏。该项目作者出于性能方面的考虑没有选择 Vue 和 React 技术栈,而是采用的 JavaScript 和 jQuery 构建,支持 Docker 一键部署…

DAC测试实验——FPGA学习笔记7

一、DAC简介 DAC全称Digital to Analog Converter,即数模转换器。它用于将主控芯片产生的数字值(0和1)转换为模拟值(电压值)。 1、DAC参数指标 2、DAC类型 常用的DAC可大致分为权电阻网络DAC、T型电阻网络DAC、倒T型电阻网络DAC以及权电流型DAC。 3、AD9708/3PD9…

2024 Testing Expo China – Automotive I 风丘与您相约上海世博馆

2024汽车测试及质量监控博览会(中国)——(Testing Expo China – Automotive)是面向整车、零部件和系统开发的各种技术和服务的盛会,展示了汽车测试、开发和验证技术的各个方面,每年在上海举行,…

微积分-导数1(导数与变化率)

切线 要求与曲线 C C C相切于 P ( a , f ( a ) ) P(a, f(a)) P(a,f(a))点的切线,我们可以在曲线上找到与之相近的一点 Q ( x , f ( x ) ) Q(x, f(x)) Q(x,f(x)),然后求出割线 P Q PQ PQ的斜率: m P Q f ( x ) − f ( a ) x − a m_{PQ} \…

Linux常用

很早以前的 ls: 查看文件夹内所有文件 rz: windows的文件传到linux服务器 sz filename: 将文件下载到windows本地 ctrlinsert:复制 shiftinsert:粘贴 ctrlD:退出spark-shell 运行脚本并输出日志 nohup sh filename.sh > log.log 2>&1 & 查看日…

Android 天气APP(八)城市切换 之 自定义弹窗与使用

然后在模块的utils包中新建一个LiWindow类 代码如下: package com.llw.mvplibrary.utils; import android.app.Activity; import android.content.Context; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; im…

【CSS in Depth2精译】1.1.4 源码顺序

解决层叠冲突的最后一环叫做 源码顺序,有时又称为 出现顺序(order of appearance)。如果其他判定规则均一致,则样式表中后出现的、或者在页面较晚引入的样式表声明,将最终胜出。 也就是说,可以通过控制源码…

fastapi+vue3+primeflex前后端分离开发项目第一个程序

安装axios axios是用来请求后端接口的。 https://www.axios-http.cn/docs/intro pnpm 是一个前端的包管理工具,当我们需要给前端项目添加新的依赖的时候,就可以使用pnpm install 命令进行安装。 pnpm install axios安装 primeflex primeflex是一个cs…

fastapi+vue3+primeflex前后端分离开发项目环境搭建

创建后端项目 创建文件夹: mkdir backend创建python虚拟环境: python -m venv venv使用Pycharm打开文件夹,然后配置python解释器为venv虚拟环境。 安装fastapi: pip install "fastapi[all]"编写第一个程序&#xf…

嵌入式通信协议----Wi-Fi协议详解(二)(基于STM32+有人物联网WIFI模块)

四、有人WIFI模块 1.模块介绍 Wi-Fi 模块用于实现串口到 Wi-Fi 数据包的双向透明转发,模块内部完成协议转换,通 过该模块,客户可以将物理设备连接到 Wi-Fi 网络上,从而实现物联网的控制与管理。 2.模块参数 Wi-Fi 模块的…

音频信号分析

目录 一,音频获取 二,信号的基本形态 三,衰减信号的频域信号 四,低频信号 五,高频信号 六,七个音节的频率 一,音频获取 我用电子琴(音色模式是卧式钢琴)&#xff…

软件测试----用例篇(设计测试用例保姆级教程✅)

文章目录 前言一、测试用例概念 二、如何设计测试用例三、设计测试用例的方法3.1基于需求的设计方法3.2具体的设计方法等价类边界值正交法判定表法场景法错误猜测法 前言 在软件开发过程中,测试用例是至关重要的一环。它们帮助软件开发人员和测试人员确定软件是否按…

5.什么是C语言

什么是 C 语言? C语言是一种用于和计算机交流的高级语言, 它既具有高级语言的特点,又具有汇编语言的特点 非常接近自然语言程序的执行效率非常高 C语言是所有编程语言中的经典,很多高级语言都是从C语言中衍生出来的, 例如:C、C#、Object-C、…

Web后端Javaee企业级开发之定时任务 Springboot整合任务框架Quartz和Task详解

定时任务 在Java EE企业级开发中,定时任务(也称为后台调度或周期性任务)是非常常见的一种功能,主要用于执行那些不需要用户交互,但需要按照预定时间间隔或事件触发的任务。Java EE提供了几个框架和API来处理这种需求&…

库卡机器人减速机维修齿轮磨损故障

一、KUKA机器人减速器齿轮磨损故障的原因 1. 润滑不足:润滑油不足或质量不佳可能导致齿轮磨损。 2. 负载过重:超过库卡机械臂减速器额定负载可能导致齿轮磨损。 3. 操作不当:未按照说明书操作可能导致KUKA机器人减速器齿轮磨损。 4. 维护不足…

【docker安装rabbitmq】

docker安装rabbitmq 1.查阅rabbitmq的Dokcer Hub官方说明 rabbitmq地址,因为我们需要使用的是带管理界面的rabbitmq服务。所以我们需要下载的rabbitmq:management镜像 docker pull rabbitmq:management2.启动rabbitmq 2.1.快速启动 One of the important thing…

[吃瓜教程]概览西瓜书+南瓜书第3章线性回归

第三章 线性模型 3.0 机器学习三要素 模型:根据问题,确定假设空间策略:根据评价标准,确定选取最优模型的策略(通常会产出一个损失函数)算法:求解损失函数,确定最优模型。 3.1基本…

Redis进阶 - 朝生暮死之Redis过期策略

概述 Redis 是一种常用的内存数据库,其所有的数据结构都可以设置过期时间,时间一到,就会自动删除。你可以想象 Redis 内部有一个死神,时刻盯着所有设置了过期时间的 key,寿命一到就会立即收割。 你还可以进一步站在死神…

“打造智能售货机系统,基于ruoyi微服务版本开源项目“

目录 # 开篇 售货机术语 1. 表设计说明 2. 页面展示 2.1 区域管理页面 2.2 合作商管理页面 2.3 点位管理页面 3. 建表资源 3.1 创建表的 SQL 语句(包含字段备注) 1. Region 表 2. Node 表 3. Partner 表 4. 创建 tb_vending_machine 表的 S…

Netty 入门实例

文章目录 1. 概述2. 代码实例2.1 服务端2.2 客户端2.3 运行截图 3. 整体结构4. 重要组件4.1 EventLoopGroup、EventLoop4.2 Handler & Pipeline4.3 ByteBuf 参考文献 1. 概述 Netty 是一款用于高效开发网络应用的 NIO 网络框架,它大大简化了网络应用的开发过程…