当前位置: 首页 > news >正文

GO语言的垃圾回收机制

内存垃圾的产生

程序在内存上被分为堆区、栈区、全局数据区、代码段、数据区五个部分。对于C++等早期编程语言栈上的内存回由编译器负责管理回收,而堆上的内存空间需要编程人员负责申请和释放。在Go中栈上内存仍由编译器负责管理回收,而堆上的内存由编译器和垃圾收集器负责管理回收,给编程人员带来了极大的便利性。

 垃圾是指程序向堆栈申请的内存空间,随着程序的运行已经不再使用这些内存空间,这时如果不释放它们就会造成垃圾,也就是内存泄漏。

 package main//假设每个人都拥有自己都一部手机type Person struct {phone *Phone}type Phone struct {money int}func main() {//定义一个Person为超超chao := new(Person)//超超一开始用的是iphone12iphone := &Phone{money: 6599}chao.phone = iphone//华为推出了鸿蒙,于是超超果断入了一部mate40huawei := &Phone{money: 5899}chao.phone = huawei}

随着超超将手机从iphone换成了华为,phone指向的内存空间就变成了垃圾,这时就需要对phone指向的内存空间进行回收,否则就变成了内存泄漏。


Golang垃圾回收机制

Go1.3采用的标记清除法,Go1.5采用三色标记法,Go1.8采用三色标记法+混合写屏障


标记清除法

分为两个阶段:标记和清除

标记阶段:从根对象出发寻找并标记所有存活的对象。

清除阶段:遍历堆中的对象,回收未标记的对象,并加入空闲链表

缺点:需要暂停程序STW

步骤:

  1. 进行STW(暂停程序业务逻辑),然后从main函数开始找到不可达的内存占用和可达的内存占用
  2. 开始标记,程序找出可达内存占用并标记
  3. 标记结束,清除未标记的内存占用
  4. 结束STW停止暂停,让程序继续执行,循环该过程直到main生命周期结束。

 一开始的做法是将垃圾清理结束时才停止STW,后来优化了方案将清理垃圾放到了STW之后,与程序运行同时进行,这样做减少了STW的时长。但是STW会暂停用户逻辑对程序的性能影响是非常大的,这种粒度的STW对于性能较高的程序还是无法接受,因此Go1.5采用了三色标记法优化了STW。


三色标记法

将对象标记为白色,灰色和黑色

白色:不确定对象(默认色) ;黑色:存活对象;灰色:存活对象,子对象待处理

步骤:

  1. 将所有对象标记为白色
  2. 从根节点集合出发,将第一次遍历到的节点标记为灰色放入到集合列表中
  3. 遍历灰色集合,将灰色节点遍历到的白色节点标记为灰色,并把灰色节点标记为黑色、
  4. 循环整个过程
  5. 直到灰色节点集合为空,回收所有白色节点

这种方法有个缺陷:如果对象的引用被用户修改了,那么之前的标记就无效了。

分析bug的根源所在,主要是因为程序在运行过程中出现了下面俩种情况

  1. 一个白色对象被黑色对象引用
  2. 灰色对象与它之间的可达关系的白色对象遭到破坏

因此在此基础上拓展出了俩种方法,强三色不变式和弱三色不变式

  1. 强三色不变式:不允许黑色对象引用白色对象
  2. 弱三色不变式:黑色对象可以引用白色,白色对象存在其他灰色对象对他的引用,或者他的链路上存在灰色对象

为了实现这俩种不变式的设计思想,从而引出了屏障机制,即在程序的执行过程中加一个判断机制,满足判断机制则执行回调函数。

 屏障机制分为插入屏障删除屏障,插入屏障实现的是强三色不变式,删除屏障则实现了弱三色不变式。值得注意的是为了保证栈的运行效率,屏障只对堆上的内存对象启用,栈上的内存会在GC结束后启用STW重新扫描。

插入屏障:对象被引用时触发的机制,当白色对象被黑色对象引用时,白色对象被标记为灰色(栈上对象无插入屏障)

缺点在于:如果对象1在栈上新创建了一个对象6,由于栈没有屏障机制,所以对象6仍为白色节点会被回收

所以栈在GC迭代结束时(没有灰色节点),会对栈执行STW,重新进行扫描清除白色节点。(STW时间为10-100ms) 

删除屏障:对象被删除时触发的机制。如果灰色对象引用的白色对象被删除时,那么白色对象会被标记为灰色

缺点:这种做法回收精度较低,一个对象即使被删除仍可以活过这一轮再下一轮被回收。(如果对象4没有引用对象3,此时对象3应该作为垃圾被回收,但是对象3却要等到下一轮GC才会被回收)

同样也存在对栈的二次扫描影响程序的效率。


三色标记+混合写屏障技术

基于插入写屏障和删除写屏障在结束时需要STW来重新扫描栈,所带来的性能瓶颈,Go在1.8引入了混合写屏障的方式实现了弱三色不变式的设计方式,混合写屏障分下面四步

  1. GC开始时将栈上可达对象全部标记为黑色(不需要二次扫描,无需STW)
  2. GC期间,任何栈上创建的新对象均为黑色
  3. 被删除引用的对象标记为灰色
  4. 被添加引用的对象标记为灰色

相关文章:

GO语言的垃圾回收机制

内存垃圾的产生 程序在内存上被分为堆区、栈区、全局数据区、代码段、数据区五个部分。对于C等早期编程语言栈上的内存回由编译器负责管理回收,而堆上的内存空间需要编程人员负责申请和释放。在Go中栈上内存仍由编译器负责管理回收,而堆上的内存由编译器…...

vim粘贴内容格式混乱解决方法

问题 复制本地文件内容后&#xff0c;咱贴到vim文本内&#xff0c;格式错乱 解决方法 打开vim配置文件 最后面加入一行 vim /etc/vimrc set pastetoggle<F11> 开发vim文件&#xff0c;进入后先按F11进入交互模式 shift insert 再次粘贴 解决...

基于Orangepi 3 lts 的云台相机

利用orangepi 3 lts 和arduino nano 制作了一个云台相机&#xff0c;可用于室内监控。 硬件&#xff1a; orangepi 3 ,arduino nano ,usb相机&#xff0c;180度舵机两个 WeChat_20230806213004 软件&#xff1a; 整体采用mqtt进行消息的中转。 相机采用python 利用opencv…...

Go重写Redis中间件 - Go实现Redis持久化

GO实现Redis持久化 项目开发到这里,我们的下一步就是实现Redis的持久化落盘功能,Redis是一个内存型的数据库,在之前我们实现的单机版Redis如果把进程杀掉,我们通过GET、SET指令存储的数据都将不复存在,数据只存在内存的map里面,重启之后什么都没有了 我们现在的目标就是…...

单元测试之 - Review一个微服务的单元测试

这里以github上一个microservice的demo代码为例&#xff0c;来看看如何为一个完整的服务编写单元测试。具体代码如下所示&#xff0c;我们重点查看一下catalog和customer&#xff0c;order中的单元测试有哪些。 首先来看catalog服务的单元测试,这个服务下面主要编写了CatalogWe…...

NetSuite 2023.2 Cash 360 功能更新

大约一年前&#xff0c;Cash 360功能推出。我们写了篇介绍&#xff1a; NetSuite Cash 360_netsuite oneworld数据可以迁移到sap上吗_NetSuite知识会的博客-CSDN博客Cash 360是在SuiteWorld 2021做的预告&#xff0c;本来是要跟着22.1发布出来&#xff0c;但是各种原因导致跳票…...

vue2-组件和插件的区别

1、组件是什么&#xff1f; 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念&#xff08;组件&#xff09;来实现开发的模式&#xff0c;在vue中每一个.vue文件都可以被视为一个组件。 组件的优势&#xff1a; 降低整个系统的耦合度&#xff0c;在保持接口不变的情况下…...

neo4j查询语言Cypher详解(一)--语法和子句

前言 neo4j的图查询语言叫Cypher。Cypher的独特之处在于它提供了一种匹配模式和关系的可视化方式。 (nodes)-[:ARE_CONNECTED_TO]->(otherNodes)使用圆角括号表示节点(nodes)&#xff0c; -[:ARROWS]->表示关系。 语法 解析 Cypher解析器接受任意输入字符串。 unico…...

PCIe总线详解

一、PCIe简介 PCI Express (peripheral component interconnect express) 简称PCIe&#xff0c;是一种高速、串行、全双工、计算机扩展总线标准&#xff0c;采用高速差分总线&#xff0c;并采用端到端的连接方式&#xff0c;因此在每一条PCIe链路中两端只能各连接一个设备。相对…...

【vim 学习系列文章 4 - vim与系统剪切板之间的交互】

文章目录 背景1.1.1 vim支持clipboard 检查1.1.2 vim的寄存器 上篇文章&#xff1a;【vim 学习系列文章 3 - vim 选中、删除、复制、修改引号或括号内的内容】 背景 从vim中拷贝些文字去其它地方粘贴&#xff0c;都需要用鼠标选中vim的文字后&#xff0c;Ctrlc、Ctrlv&#x…...

代码随想录算法训练营第五十六天| 583. 两个字符串的删除操作 72. 编辑距离

代码随想录算法训练营第五十六天| 583. 两个字符串的删除操作 72. 编辑距离 一、力扣583. 两个字符串的删除操作 题目链接 思路&#xff1a;相等时不删除&#xff0c;不相等时&#xff0c;两个字符串各删除一个&#xff0c;比大小&#xff0c;删除用步骤少的。 class Soluti…...

Mac强制停止应用

有时候使用Mac的时候&#xff0c;某个应用卡住了&#xff0c;但是肯定不能因为一个应用卡住了&#xff0c; 就将电脑重启吧&#xff0c;所以只需要单独停止该应用即可&#xff0c;使用快捷键optioncommandesc就会出现强制停止的界面&#xff0c;选择所要停止的应用&#xff0c;…...

Linux系统Redis的哨兵架构配置

Linux系统Redis的哨兵架构配置 此处基于 Linux系统Redis的主从架构配置 进行哨兵高可用架构的搭建 此案例在一台虚拟机上启动6379和6380和6381三个reids主从实例&#xff08;6379为主节点&#xff0c;6380和6381为从节点&#xff09;&#xff0c;以及26379、26380、26381的sent…...

HarmonyOS/OpenHarmony-ArkTS基于API9元服务开发快速入门

一、创建项目 二、创建卡片 三、添加资源 四、具体代码 Entry Component struct WidgetNewCard {/** The title.*/readonly TITLE: string harmonyOs;readonly CONTEXT: string 技术构建万物智联;/** The action type.*/readonly ACTION_TYPE: string router;/** The…...

macbook怎么卸载软件?2023年最新全新解析macbook电脑怎样删除软件

macbook怎么卸载软件&#xff1f;2023年最新全新解析macbook电脑怎样删除软件。关于Mac笔记本如何卸载软件_Mac笔记本卸载软件的四种方法的知识大家了解吗&#xff1f;以下就是小编整理的关于Mac笔记本如何卸载软件_Mac笔记本卸载软件的四种方法的介绍&#xff0c;希望可以给到…...

c51单片机16个按键密码锁源代码(富proteus电路图)

注意了&#xff1a;这个代码你是没法直接运行的&#xff0c;但是如果你看得懂&#xff0c;随便改一改不超过1分钟就可以用 #include "reg51.h" #include "myheader.h" void displayNumber(unsigned char num) {if(num1){P10XFF;P10P11P14P15P160;}else if…...

GraalVM

一、GraalVM GraalVM 是由 Oracle 开发的一个高性能、高效的通用虚拟机。它是一个全球性的项目&#xff0c;涵盖了多种编程语言和平台&#xff0c;并为开发者提供了一种统一的虚拟机环境。GraalVM 的核心特性是支持多语言混合执行&#xff0c;即在同一个运行时环境中同时执行多…...

File 类和 InputStream, OutputStream 的用法总结

目录 一、File 类 1.File类属性 2.构造方法 3.普通方法 二、InputStream 1.方法 2.FileInputStream 三、OutputStream 1.方法 2.FileOutputStream 四、针对字符流对象进行读写操作 一、File 类 1.File类属性 修饰符及类型属性说明static StringpathSeparator依赖于系统的路…...

开源进展 | WeBASE v3.1.0发布,新增多个实用特性

WeBASE是一个友好、功能丰富的区块链中间件平台&#xff0c;通过一系列通用功能组件和实用工具&#xff0c;助力社区开发者更快捷地与区块链进行交互。 目前WeBASE已更新迭代至v3.1.0版本&#xff0c;本次更新中&#xff0c;WeBASE带来了最新的合约Java脚手架导出功能&#xff…...

C++动态加载 插件

动态加载&#xff08;Dynamic Loading&#xff09;是指在程序运行时&#xff0c;根据需要动态地加载和链接代码或资源。 动态加载的主要目的是实现程序的灵活性和可扩展性&#xff0c;以及减少内存消耗和启动时间。通过动态加载&#xff0c;程序可以根据运行时的需求加载特定的…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...