Go 垃圾回收(GC)

之前自以为对Go语言的GC了如指掌,结果昨天被面试官疯狂拷打。于是有了这篇博客。

Go语言的GC主要有三个版本:

  • v1.3 标记清除法
  • v1.5 三色标记法 + 写屏障
  • v1.8 混合写屏障

v1.3标记清除法

Go1.3的标记清除法是Go语言早期版本的垃圾收集策略。这种方法在垃圾收集过程中需要暂停整个程序(Stop-the-World,STW),这可能对程序的性能产生负面影响。标记清除法可以在大体上分为四个步骤:

  1. STW,暂停运行中的程序
  2. 根节点出发,标记出所有可达对象
  3. 清除所有未被标记的对象
  4. 程序恢复运行

缺点

  1. 执行期间需要把整个程序完全暂停,不能异步的进行垃圾回收。
  2. 标记阶段需要扫描整个堆内存以找出所有可达对象,这可能会消耗大量时间和计算资源。
  3. 容易产生大量不连续的内存碎片,碎片太多可能会导致后续没有足够的连续内存分配给较大的对象,从而提前触发新的一次垃圾收集动作。

v1.5三色标记法+写屏障

Go1.5版本的GC采用的是三色标记法+写屏障。

三色标记法

Go 三色标记法是一种并发的垃圾回收算法。
三色标记法将对象分为三类:

  • 白色对象:未被标记的对象
  • 灰色对象:正在被标记的对象
  • 黑色对象:已经被标记的对象

流程如下:

  1. 初始时,所有的对象为白色。
  2. 根对象开始,将能够直达的对象标记为灰色,放入灰色队列中。
  3. 从灰色队列中取出一个灰色对象,将其引用的对象放入灰色队列。将该灰色对象标记为黑色,并移除灰色队列。
  4. 重复上面的过程,直至灰色队列为空。
  5. 清除所有白色对象。

在没有用户态代码并发修改三色关系的情况下,回收可以正常结束。
假设某个灰色对象A指向白色对象B,此时并发的用户态代码将黑色对象C指向了白色对象B,并将灰色对象A对白色对象B的引用移除,则在继续扫描的过程中,白色对象B永远不会被标记为黑色对象。进而对象B被错误回收。
为了解决这种问题,引入了写屏障。

三色不变式

三色不变式是确保三色标记法正确的关键条件。它要求在整个标记过程中,以下两个条件始终成立:

  1. 强三色不变式:不允许黑色对象直接应用白色对象。
  2. 弱三色不变式:所有被黑色对象引用的白色对象都必须通过灰色对象可达。

写屏障

当一个对象引用另外一个对象时,将另外一个对象标记为灰色,以此满足强三色不变式,不会存在黑色对象引用白色对象。

v1.8三色标记法+混合写屏障

在Go1.8 GC策略中,进一步将写屏障优化为了混合写屏障。

混合写屏障

混合写屏障分为:插入写屏障和删除写屏障

  1. 插入写屏障:当一个黑色对象引用了一个白色对象时,插入写屏障会被触发,此时垃圾收集器会将该白色对象被标记为灰色对象。
  2. 删除写屏障:当一个对象的引用被删除时,删除写屏障会被触发。此时垃圾收集器会将该对象标记为灰色。

根对象是个啥

Go语言的GC根对象主要包括全局变量、执行栈、寄存器中的指针以及其他运行时数据结构中的指针。

  1. 全局变量:全局变量是在程序整个生命周期中都可以访问的变量。由于它们在程序开始时就已经存在,因此被视为根对象的一部分。
  2. 执行栈:每个Goroutine 都有自己的执行栈。执行栈上包含的函数局部变量以及指向堆上分配的对象的指针都会被视为根对象。
  3. 缓存器:在某些情况下,寄存器的值可能表示一个指针。这些指针可能指向某些由Go程序分配的堆内存区块。虽然寄存器的访问通常是与CPU架构和具体实现紧密相关的,但GC在特定的情况下也会将寄存器中的指针作为根对象来扫描。
  4. 其他运行时数据结构:Go语言的运行时系统维护了一些其他的数据结构,如mcache、span等。这些数据结构中的某些部分也可能包含指向堆内存区块的指针,因此它们也可能被视为根对象。

GC回收触发时机

内存分配达到阀值触发

每次内存分配时都会检查当前内存分配量是否已达到阀值,如果达到阀值则立即启动GC。
阀值 = 上次GC内存分配量 * 内存增长率
内存增长率由环境变量GOGC控制,默认为100,即当内存扩大一倍时启动GC。

定期触发GC

默认情况下,最长2分钟触发一次GC,这个间隔在src/runtime/proc.go:forcegcperiod变量中被声明:

// forcegcperiod is the maximum time in nanoseconds between garbage
// collections. If we go this long without a garbage collection, one
// is forced to run.
//
// This is a variable for testing purposes. It normally doesn't change.
var forcegcperiod int64 = 2 * 60 * 1e9 

手动触发

程序中可以通过 runtime.GC()来手动触发GC

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

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

相关文章

java并发编程之美-第1章 并发编程线程基础-线程通知与等待(wait/notify,notifyAll)

文章目录 前言1. wait()函数 前言 Object类是所有类的父类,鉴于继承机制,Java把所有类都需要的方法放到了 Obiect类里面,其中就包含通知(notify,notifyAll)与等待(wait)系列函数。 1. wait()函数 当一个…

SpringBoot使用Redisson操作Redis及使用场景实战

前言 在SpringBoot使用RedisTemplate、StringRedisTemplate操作Redis中,我们介绍了RedisTemplate以及如何SpringBoot如何通过RedisTemplate、StringRedisTemplate操作Redis。 RedisTemplate的好处就是基于SpringBoot自动装配的原理,使得整合redis时比较…

【力扣C语言】每日一题—第387题,字符串中第一个唯一字符

题目: 给出一串字符串,找出其中第一个不重复的字符,返回它的索引 思路: 暴力求解: 1、算字符串长度 2、while循环作为外循环,for循环作为内循环,依次遍历,如果有相同的跳过&…

防火墙安全策略练习

目录 实验拓扑 实验要求 实验思路 实验步骤 1.配置交换机,划分接口的vlan,配置ISP 2.配置防火墙 3.接下来在WEB界面进行所有安全策略操作 配置接口 创建安全区域: 创建地址: 时间段: 安全策略部分&#xff…

地理信息科学在灾害管理中的应用:GIS构建防灾减灾的智慧防线

在全球气候变化与人类活动加剧的背景下,自然灾害频发,给社会经济发展带来了严峻挑战。本文将深入分析GIS在灾害预测、评估和响应中的核心作用,展示其如何为构建更加安全、韧性的社会提供智慧解决方案。 灾害预测:GIS的“先知”之…

JavaScript青少年简明教程:为何学习JavaScript及JavaScript简介

JavaScript青少年简明教程:为何学习JavaScript及JavaScript简介 JavaScript最初是为web浏览器(前端开发)设计的。它可以在所有现代浏览器中运行,包括Chrome, Firefox, Safari, Edge等。 这意味着JavaScript代码可以在任何能运行…

docker中mysql设置lower_case_table_names配置的坑

前沿 今天在使用flowable流程框架的时候,遇到一个问题。需要配置MySQL数据库以实现表名大小写不敏感。本以为这是一个简单的任务,却耗费了我两个多小时的时间。 docker容器中修改配置,重启不成功 我们前提是容器中的mysql中已经有很多数据…

FastAPI -- 第一弹(查询参数/路径参数/请求体参数)

Hello World 经典的 Hello World 安装 pip install fastapi pip install "uvicorn[standard]"main.py from typing import Unionfrom fastapi import FastAPIapp FastAPI()app.get("/") def read_root():return {"Hello": "World"}…

判断链表中是否有环(力扣141.环形链表)

这道题要用到快慢指针。 先解释一下什么是快慢指针。 快慢指针有两个指针,走得慢的是慢指针,走得快的是快指针。 在这道题,我们规定慢指针一次走一步,快指针一次走2步。 如果该链表有环,快慢指针最终会在环中相遇&a…

微调及代码

一、微调:迁移学习(transfer learning)将从源数据集学到的知识迁移到目标数据集。 二、步骤 1、在源数据集(例如ImageNet数据集)上预训练神经网络模型,即源模型。 2、创建一个新的神经网络模型&#xff…

大数据基础:Hadoop之Yarn重点架构原理

文章目录 Hadoop之Yarn重点架构原理 一、Yarn介绍 二、Yarn架构 三、Yarn任务运行流程 四、Yarn三种资源调度器特点及使用场景 Hadoop之Yarn重点架构原理 一、Yarn介绍 Apache Hadoop Yarn(Yet Another Reasource Negotiator,另一种资源协调者)是Hadoop2.x版…

LLM-向量数据库中的索引算法总结

文章目录 前言向量数据库介绍索引方法倒排索引KNN 搜索近似 KNN 搜索Product Quantization(PQ)NSW 算法搜索HNSW 前言 向量数据库是当今大模型知识库检索落地实践的核心组件,下图是构建知识库检索的架构图: 首先会将相关文档数据向量化嵌入到向量化数据…

Python Linux下编译

注意 本教程针对较新Linux系统,没有升级依赖、处理旧版本Linux的openssl等步骤,如有需要可以查看往期文章,例如:在Centos7.6镜像中安装Python3.9 教程中没有使用默认位置、默认可执行文件名,请注意甄别 安装路径&#…

vue3中echarts的使用

1.下载 echartsnpm i -s echarts 2.在main.js中引入import { createApp } from vue import App from ./App.vue// 引入 echarts import * as echarts from echarts const app createApp(App) // 全局挂载 echarts app.config.globalProperties.$echarts echartsapp.mount(#ap…

I18N/L10N 历史 / I18N Guidelines I18N 指南 / libi18n 模块说明

注&#xff1a;机翻&#xff0c;未校对。 文章虽然从 Netscape 客户端展开 I18N/L10N 历史&#xff0c;但 I18N/L10N 的演化早已不仅限适用于 Netscape 客户端。 Netscape Client I18N/L10N History Netscape 客户端 I18N/L10N 历史 Contact: Bob Jung <bobjnetscape.com&…

阿里生态体系

阿里巴巴的“16N”战略框架是一种业务布局战略。具体来说&#xff0c;“1”代表核心电商平台&#xff0c;“6”代表阿里的六大板块&#xff0c;“N”代表众多的新业务和创新业务。以下是对“16N”具体内容的详细说明&#xff1a; 1. 核心电商平台 阿里巴巴电子商务业务&#…

Go语言入门之数组切片

Go语言入门之数组切片 1.数组的定义 数组是一组连续内存空间存储的具有相同类型的数据&#xff0c;是一种线性结构。 在Go语言中&#xff0c;数组的长度是固定的。 数组是值传递&#xff0c;有较大的内存开销&#xff0c;可以使用指针解决 数组声明 var name [size]typename&…

达梦数据库dm8安装步骤及迁移

目录 前言: 一、安装部署 1、下载 2、创建用户及安装目录 3、挂载下载的镜像 4、环境配置 5、安装 二、基本使用 1、DM工具使用 2、兼容性配置 2.1 兼容GBK字符集编码 2.2 兼容UTF-8字符集编码 3、创建用户和密码,表空间 4、整理数据库配置 5、启动脚本设置 …

华为OD机考题(HJ74 参数解析)

前言 经过前期的数据结构和算法学习&#xff0c;开始以OD机考题作为练习题&#xff0c;继续加强下熟练程度。 描述 在命令行输入如下命令&#xff1a; xcopy /s c:\\ d:\\e&#xff0c; 各个参数如下&#xff1a; 参数1&#xff1a;命令字xcopy 参数2&#xff1a;字符串…

JavaSE学习笔记之内部类、枚举类和基本类型包装类

今天我们继续复习Java相关的知识&#xff0c;和大家分享有关内部类等方面的知识&#xff0c;希望大家喜欢。 目录​​​​​​​ 内部类 成员内部类 ​编辑 静态内部类 局部内部类 匿名内部类 枚举类 定义方法 基本类型包装类 自动装箱和拆箱 内部类 成员内部类 成…