Go语言设计与实现 -- GC的简要介绍

news2024/9/29 9:21:59

GC实现原理

什么是GC?

垃圾回收也称为GC(Garbage Collection),是一种自动内存管理机制

现代高级编程语言管理内存的方式分为两种:自动和手动,像C、C++ 等编程语言使用手动管理内存的方式,工程师编写代码过程中需要主动申请或者释放内存;而 PHP、Java 和 Go 等语言使用自动的内存管理系统,有内存分配器和垃圾收集器来代为分配和回收内存,其中垃圾收集器就是我们常说的GC。

在应用程序中会使用到两种内存,分别为堆(Heap)和栈(Stack),GC负责回收堆内存,而不负责回收栈中的内存:

栈是线程的专用内存,专门为了函数执行而准备的,存储着函数中的局部变量以及调用栈,函数执行完后,编译器可以将栈上分配的内存可以直接释放,不需要通过GC来回收。

堆是程序共享的内存,需要GC进行回收在堆上分配的内存。

垃圾回收器的执行过程被划分为两个半独立的组件

  • 赋值器(Mutator):这一名称本质上是在指代用户态的代码。因为对垃圾回收器而言,用户态的代码仅仅只是在修改对象之间的引用关系,也就是在对象图(对象之间引用关系的一个有向图)上进行操作。
  • 回收器(Collector):负责执行垃圾回收的代码。

主流的GC算法

目前比较常见的垃圾回收算法有3种:

  • 引用计数:为每个对象维护一个引用计数,当引用该对象的对象销毁时,引用计数-1,当对象引用计数为0时回收该对象。
    • 代表语言:PythonPHPSwift
    • 优点:对象回收快,不会出现内存耗尽或达到某个阈值时才回收。
    • 缺点:不能很好的处理循环引用,而实时维护引用计数也是有损耗的。
  • 分代收集:按照对象生命周期长短划分不同的代空间,生命周期长的放入老年代,短的放入新生代,不同代有不同的回收算法和回收频率。
    • 代表语言:Java
    • 优点:回收性能好
    • 缺点:算法复杂
  • 标记-清除:从根变量开始遍历所有引用的对象,标记引用的对象,没有被标记的进行回收。
    • 代表语言:Golang(三色标记法)
    • 优点:解决了引用计数的缺点。
    • 缺点:需要 STW,暂时停掉程序运行。

img

Go GC算法

此算法是在Go1.5版本开始使用,Go采用的是标记清除算法,并在此基础上使用了三色标记法混合写屏障技术,GC过程和其他用户goroutine可并发运行,但需要一定时间的STW

三色标记法只是为了叙述方便而抽象出来的一种说法,实际上的对象是没有三色之分的。这里的三色,对应了垃圾回收过程中对象的三种状态:

  • 灰色:对象还在标记队列中等待
  • 黑色:对象已被标记,gcmarkBits对应位为1(该对象不会在本次GC中被回收)
  • 白色:对象未被标记,gcmarkBits对应位为0(该对象会在本次GC中被清理)

垃圾回收过程:

  • 创建:白,灰,黑三个集合
  • 将所有对象放入白色集合中
  • 遍历所有root对象,把遍历到的对象从白色集合放入灰色集合(这里放入灰色集合的都是根节点的对象)
  • 遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,自身标记为黑色
  • 重复步骤4,直到灰色中无任何对象,其中用到2个机制:
    • 写屏障(Write Barrier):上面说到的STW目的是防止GC扫描时内存变化引起的混乱,而写屏障就是让Goroutine与GC同时运行的手段,虽然不能完全消除STW,但是可以大大减少STW时间。写屏障在GC的特定时间开启,开启后指针传递时会把指针标记,即本轮不回收,下次GC时再确定
    • 辅助 GC(Mutator Assist):为了防止内存分配过快,在 GC 执行过程中,GC 过程中 mutator 线程会并发运行,而 mutator assist 机制会协助 GC 做一部分的工作。
  • 收集所有白色对象(垃圾)

root对象

根对象在垃圾回收的术语中又叫做根集合,它是垃圾回收器在标记过程时最先检查的对象,包括:

全局变量:程序在编译期就能确定的那些存在于程序整个生命周期的变量。 执行栈:每个 goroutine 都包含自己的执行栈,这些执行栈上指向堆内存的指针。 寄存器:寄存器的值可能表示一个指针,参与计算的这些指针可能指向某些赋值器分配的堆内存区块。

插入写屏障

对象被引用时触发的机制(只在堆内存中生效):赋值器这一行为通知给并发执行的回收器,被引用的对象标记为灰色

缺点:结束时需要STW来重新扫描栈,标记栈上引用的白色对象的存活

删除写屏障

对象被删除时触发的机制(只在堆内存中生效):赋值器将这一行为通知给并发执行的回收器,被删除的对象,如果自身为灰色或者白色,那么标记为灰色

缺点:一个对象的引用被删除后,即使没有其他存活的对象引用它,它仍然会活到下一轮,会产生很大冗余扫描成本,且降低了回收精度

混合写屏障

GC没有混合写屏障前,一直是插入写屏障;混合写屏障是插入写屏障 + 删除写屏障,写屏障只应用在堆上应用,栈上不启用(栈上启用成本很高)

  • GC开始将栈上的对象全部扫描并标记为黑色。
  • GC期间,任何在栈上创建的新对象,均为黑色。
  • 被删除的对象标记为灰色。
  • 被添加的对象标记为灰色。

GC流程

一次完整的垃圾回收会分为四个阶段,分别是标记准备、标记开始、标记终止、清理:

  1. 标记准备(Mark Setup):打开写屏障(Write Barrier),需 STW(stop the world)
  2. 标记开始(Marking):使用三色标记法并发标记 ,与用户程序并发执行
  3. 标记终止(Mark Termination):对触发写屏障的对象进行重新扫描标记,关闭写屏障(Write Barrier),需 STW(stop the world)
  4. 清理(Sweeping):将需要回收的内存归还到堆中,将过多的内存归还给操作系统,与用户程序并发执行

img

GC的触发时机

主动触发:

  • 调用 runtime.GC() 方法,触发 GC

被动触发:

  • 定时触发,该触发条件由 runtime.forcegcperiod 变量控制,默认为 2 分 钟。当超过两分钟没有产生任何 GC 时,触发 GC
  • 根据内存分配阈值触发,该触发条件由环境变量GOGC控制,默认值为100(100%),当前堆内存占用是上次GC结束后占用内存的2倍时,触发GC

GC如何调优

  • 控制内存分配的速度,限制Goroutine的数量,提高赋值器mutator的CPU利用率(降低GC的CPU利用率)
  • 少量使用+连接string
  • slice提前分配足够的内存来降低扩容带来的拷贝
  • 避免map key对象过多,导致扫描时间增加
  • 变量复用,减少对象分配,例如使用sync.Pool来复用需要频繁创建临时对象,使用全局变量
  • 增大GOGC的值,降低GC的运行频率

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

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

相关文章

OpenHarmony 标准系统 HDF 框架音视频驱动开发

OpenHarmony 标准系统 HDF 框架音视频驱动开发引言OpenHarmony 音频概述HDF 音频驱动框架概述HDF 音频驱动框架分析 —— 音频设备驱动HDF 音频驱动框架分析 —— supportlibs 实现HDF 音频驱动框架分析 —— hdi-passthrough 实现HDF 音频驱动框架分析 —— hdi-binder 实现HD…

从零开始计算机网络——计算机网络课程的了解初步认识计算机网络

目录 🍘计算机网络学科到底学什么? 🧇两个参考模型的介绍 🥪OSI参考模型&TPC参考模型&五层参考模型 🍱 计算机网络学科的重难点——网络协议 🥘如何学好计算机网络课程? 🍣相…

Java使用BigDecimal(公式精确计算)+(精度丢失问题)

一、Java使用BigDecimal公式计算(精确计算) 介绍: 使用BigDecimal加减乘除方法运算,可以使用BigDecimal类提供的add、subtract、multiply、divide方法函数实现。 公式加法计算~add public static void main(String[] args){BigDecimal a BigDecimal.valueOf(5.6);…

动态规划合集

62 斐波那契数列 public class Solution {public int Fibonacci(int n) { return f(n);}public int f(int n){if(n1||n2){return 1;}return f(n-1)f(n-2);} }这种做法时间复杂度O(2^N),空间复杂度是用递归栈,O(n) 改进:用动态规划,可以…

Pytorch优化器全总结(三)牛顿法、BFGS、L-BFGS 含代码

目录 写在前面 一、牛顿法 1.看图理解牛顿法 2.公式推导-三角函数 3.公式推导-二阶泰勒展开 二、BFGS公式推导 三、L-BFGS 四、算法迭代过程 五、代码实现 1.torch.optim.LBFGS说明 2.使用LBFGS优化模型 优化器系列文章列表 Pytorch优化器全总结(一&…

C 程序设计教程(09)—— 数据输出函数(printf)用法详解

C 程序设计教程(09)—— 数据输出函数(printf)用法详解 该专栏主要介绍 C 语言的基本语法,作为《程序设计语言》课程的课件与参考资料,用于《程序设计语言》课程的教学,供入门级用户阅读。 目录…

Python小案例

1、简单的打印输出 age =18 print("我的名字是%s,我的国籍是%s"%("小张","中国")) print("我的年纪是:%d岁"%age) print("www","baidu","com",sep=".") #sep是使用.分割的意思,这个输出是百…

微信小程序开发——小程序的宿主环境API,协同工作和发布

一.小程序API概述 小程序中的 API 是由宿主环境提供的,通过这些丰富的小程序 API ,开发者可以方便的调用微信提供的能力,例如:获取用户信息、本地存储、支付功能等。 二.小程序API的3大分类 a.事件监听AP1 特点:以…

【服务器数据恢复】服务器硬盘掉线的数据库数据恢复案例

服务器数据恢复环境&故障: 某公司服务器,配备24块FC硬盘,两块硬盘出现故障掉线,导致服务器上层的卷无法挂载。 服务器数据恢复过程: 1、查看服务器硬盘状态发现有两块硬盘离线,将服务器内的所有硬盘做好…

【数据结构-JAVA】栈(Stack)和队列(Queue)

栈1.1 栈的概念栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈 顶,另一端称为栈底。栈中的数据元素遵守先进后出,后进先出的原则(LIFO——Last In First Out&a…

【从零开始学习深度学习】41. 算法优化之RMSProp算法【基于AdaGrad算法的改进】介绍及其Pytorch实现

上一篇文章AdaGrad算法中提到,因为调整学习率时分母上的变量st\boldsymbol{s}_tst​一直在累加按元素平方的小批量随机梯度,所以目标函数自变量每个元素的学习率在迭代过程中一直在降低(或不变)。因此,当学习率在迭代早…

LeetCode 45. 跳跃游戏 II

45. 跳跃游戏 II - 力扣(LeetCode) 解法1:(动态规划 贪心) 果然代码越短,思路越难。这题用的是动态规划贪心的思想。首先分析题意我们可以知道,从索引0这个点开始,我们走一步可以…

redis命令第二弹

1、redis命令-hash类型练习2、redis命令-list类型练习3、redis命令-set类型练习

YOLOV5环境搭建以及训练COCO128数据集

前言记录了自己训练coco128的全过程手把手教你YOLOV5环境搭建以及训练COCO128数据集。相关配置文件在百度网盘中。如果懒得话可以直接全部用我的数据一、准备工作1.1创建环境打开anaconda power shell(最好以管理员身份运行,免得到后面相关文件权限进不去…

sentinel-介绍(一)

Sentinel Website(Sentinel 官网网站) Sentinel: 分布式系统的流量防卫兵 Sentinel 是什么? 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、流量路由、熔断降级、系…

ansible配置yum源仓库

1.挂载本地光盘到/mnt 2.配置yum源仓库文件通过多种方式实现 仓库1 : Name: RH294_Base Description: RH294 base software Base urt: file:///mnt/BaseOS 不需要验证钦件包 GPG 签名 启用此软件仓库 仓库 2: Name: RH294_S…

LeetCode刷题模版:41 - 50

目录 简介41. 缺失的第一个正数42. 接雨水43. 字符串相乘44. 通配符匹配45. 跳跃游戏 II46. 全排列47. 全排列 II48. 旋转图像49. 字母异位词分组50. Pow(x, n)结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标…

axios系列之取消请求

文章の目录写在最后使用 cancel token 取消请求 Axios 的 cancel token API 基于cancelable promises proposal,它还处于第一阶段。 可以使用 CancelToken.source 工厂方法创建 cancel token,像这样: const CancelToken axios.CancelToken;…

Revit二次开发小技巧(十七)实时监控模型线的生成

前言:项目中需要一个需求,用户想调用出Revit中自带的绘制模型线方法,然后再绘制结束时,可以拿到绘制的模型线,然后实现后面的算法。这里记录一种方法,通过DocumentChange事件修改Tag的PropertyChanged事件来…

【Python】pandas获取全省人口数据并作可视化分析

前言 今天我们看看自己所在的省份的人口人数,使用pandas并作可视化分析。 环境使用 python 3.9pycharm 模块使用 pandasPandas 是基于NumPy的一种工具,该工具是为解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供…