Go 语言的垃圾回收(Garbage Collection,简称 GC)是其自动内存管理的核心机制,旨在自动识别并回收不再被使用的内存,避免内存泄漏,减轻开发者的手动内存管理负担。Go 的 GC 算法经历了多次迭代优化,目前采用的是并发标记 - 清除(Concurrent Mark and Sweep) 算法,并结合了多种优化技术,以实现低延迟、高吞吐量的目标。

一、Go 垃圾回收的核心目标

Go 的 GC 设计围绕以下核心目标展开:

  1. 低延迟:尽可能减少 GC 对程序运行的阻塞时间(Stop-The-World,简称 STW),避免影响用户程序的响应速度。
  2. 高吞吐量:在保证低延迟的同时,高效地回收内存,减少 GC 本身的性能开销。
  3. 简单高效:算法实现简洁,适配 Go 语言的并发模型(如 goroutine)和内存分配机制。

二、Go 垃圾回收的核心算法:并发标记 - 清除(Concurrent Mark and Sweep)

Go 的 GC 基于追踪式垃圾回收(通过追踪对象的引用关系判断是否存活),核心流程分为标记(Mark) 和清除(Sweep) 两个阶段,且大部分工作在用户程序运行的同时(并发)执行,仅在关键节点需要短暂 STW。

[初始标记] → [并发标记] → [重新标记] → [并发清除](STW)       (并发)       (STW)        (并发)
1. 标记阶段(Mark Phase)

标记阶段的目标是识别出所有存活的对象(被当前程序直接或间接引用的对象),具体流程如下:

  • 初始标记(Initial Mark,STW)

    • 这是标记阶段的第一个步骤,需要短暂 STW(通常只有几微秒到几十微秒)。
    • GC 会暂停所有用户 goroutine,从根对象(Root Set)开始标记直接引用的对象。根对象包括:
      • 全局变量(如包级变量);
      • 当前运行的 goroutine 的栈内存(局部变量、函数参数等);
      • 寄存器中的引用(暂存的变量指针)。
    • 初始标记完成后,立即恢复用户程序运行。
  • 并发标记(Concurrent Mark)

    • 初始标记后,用户程序继续运行,GC 同时在后台(由专门的 GC 协程)进行标记。
    • 后台 GC 协程会从初始标记的对象出发,递归遍历所有可达的对象(通过对象的引用指针),并标记为 “存活”。
    • 由于用户程序在运行时可能修改对象的引用关系(如新增、删除指针),Go 采用写屏障(Write Barrier) 技术跟踪这些修改,确保标记的准确性:
      • 写屏障会在用户程序修改指针时(如 a = &b)触发,记录指针的变化,防止并发标记时遗漏或误判对象的存活状态。
  • 重新标记(Remark,STW)

    • 并发标记结束后,需要再次短暂 STW,处理并发标记期间因用户程序修改引用而产生的 “漏标” 对象(称为 “浮动垃圾” 的一部分)。
    • 重新标记会利用写屏障记录的指针变化,快速修正标记结果,确保所有存活对象都被标记。
2. 清除阶段(Sweep Phase)

清除阶段的目标是回收未被标记的对象(即垃圾)所占用的内存,具体流程如下:

  • 并发清除(Concurrent Sweep)
    • 清除阶段完全并发执行,不阻塞用户程序。
    • GC 会遍历堆内存,释放所有未被标记的对象(垃圾),并将其内存块归还给空闲内存池,供后续内存分配使用。
    • 清除过程中,若用户程序需要分配新内存,会优先复用已回收的空闲内存,减少内存碎片。

三、Go GC 的关键优化技术

为实现低延迟和高吞吐量,Go 引入了多项优化技术:

1. 写屏障(Write Barrier)
  • 作用:在并发标记阶段,跟踪用户程序对指针的修改,防止因引用关系变化导致的标记错误。
  • 实现:Go 使用Dijkstra 写屏障(早期版本)和混合写屏障(Go 1.8 及以后,结合了 Dijkstra 和 Yuasa 写屏障的优势),在指针赋值时插入额外逻辑,记录旧指针和新指针的信息,确保并发标记的准确性。
  • Dijkstra 写屏障:当修改指针时,将旧指针指向的对象标记为灰色(防止旧对象被漏标)
  • Yuasa 写屏障:当修改指针时,将新指针指向的对象标记为灰色(防止新对象被漏标)
  • // 伪代码:指针赋值时触发的写屏障
    func writeBarrier(old *T, new *T) {// 1. 将旧指针指向的对象标记为灰色(Dijkstra 逻辑)gray(old)// 2. 将新指针指向的对象标记为灰色(Yuasa 逻辑)gray(new)
    }

2. 三色标记法(Tri-Color Marking)
  • 标记阶段通过 “三色” 区分对象的状态,简化并发标记的管理:
    • 白色:未被标记的对象(初始状态,可能是垃圾);
    • 灰色:已被标记,但引用的子对象尚未遍历(待处理);
    • 黑色:已被标记,且所有子对象都已遍历(确定存活)。
  • 流程:初始标记将根对象设为灰色,并发标记时将灰色对象的子对象标记为灰色、自身设为黑色,最终所有黑色对象为存活,白色为垃圾。
3. 增量 GC 与并发执行
  • Go 的 GC 不是一次性完成所有工作,而是将标记和清除阶段拆分为可中断、可并发的步骤,大部分工作与用户程序并行执行,仅在初始标记和重新标记阶段短暂 STW,大幅降低了对程序运行的影响。
4. 内存分代(Generational GC)的部分实现
  • 虽然 Go 没有严格的 “分代” 设计(如 Java 的新生代、老年代),但通过对象年龄判断(如频繁分配和回收的小对象更可能被优先处理)和内存块大小分类(如 tiny、small、large 分配器),优化了 GC 对短期对象的回收效率。
5. 自适应触发机制
  • GC 触发时机并非固定,而是根据内存分配速率、堆内存大小等动态调整:
    • 当堆内存增长到上次 GC 后堆大小的 2 倍(可通过 GOGC 环境变量调整,默认 100)时触发;
    • 若内存分配速率过快,也会提前触发,避免内存溢出。

三、Go GC 的演进历程

Go 的 GC 算法经过多次重大优化,核心版本演进如下:

  • Go 1.0:采用简单的标记 - 清除算法,STW 时间长(毫秒级)。
  • Go 1.5:引入并发标记 - 清除,STW 时间缩短至百微秒级。
  • Go 1.8:使用混合写屏障,进一步减少 STW 时间(通常低于 100 微秒)。
  • Go 1.12+:优化了重新标记阶段的效率,引入更多并发优化,使 STW 时间可稳定在微秒级。

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

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

相关文章

imx6ull-驱动开发篇23——Linux 内核定时器实验

目录 实验程序编写 修改设备树文件 定时器驱动程序 timer.c 测试 timerApp.c Makefile 文件 运行测试 实验程序编写 本讲实验,我们使用正点原子I.MX6U-ALPHA 开发板,通过linux内核定时器周期性的点亮和熄灭开发板上的 LED 灯, LED 灯…

IPTV系统:开启视听与管理的全新篇章

在当今数字化飞速发展的时代,IPTV系统正以前所未有的姿态,重塑着我们的视听体验与管理模式。它不仅仅是一套技术系统,更是连接信息、沟通情感、提升效率的桥梁,为各个领域带来了全新的变革与发展机遇。从电视直播的角度来看&#…

PyTorch笔记9----------Cifar10图像分类

1.图像分类网络模型框架解读 分类网络的基本结构 数据加载模块:对训练数据加载数据重组:组合成网络需要的形式,例如预处理、增强、各种网络处理、loss函数计算优化器 数据加载模块 使用公开数据集:torchvision.datasets使用自定义…

飞凌OK3568开发板QT应用程序编译流程

飞凌OK3568开发板QT应用程序编译流程开发环境:ubuntu20.04(主机)、飞凌OK3568开发板一般在linux系统下开发用于ARM开发板的QT应用程序时,直接在主机上开发然后进行交叉编译即可,但有时候ARM开发板的厂家提供的SDK中可能…

飞算JavaAI合并项目实战:7天完成3年遗留系统重构

引言 企业数字化进程中,遗留系统改造始终是CIO面临的头号难题。某电商平台的实践数据显示:3年以上的Java项目平均存在47%的冗余代码,63%的架构设计不符合当前业务需求,进行系统性重构需要投入相当于原开发量200%的资源。传统&quo…

卫星速度增量和比冲及推力之间的关系

一、定义1.1.比冲(Isp):比冲是衡量发动机性能的重要指标,反映了单位重量推进剂在发动机中产生的冲量,单位为米/秒(m/s),代表燃料燃烧时喷流速度。这个单位与速度单位“米/秒”相同&a…

MATLAB绘制各种心形曲线

1.方程(1)心形线的经典隐函数方程为:(2)参数方程(更平滑的心形):(3)极坐标心形线(4)参数方程(3D心形)(5)隐函数3D心形2. MATLAB代码clc;close all;clear all;warning off;%清除变量 rand(seed, 100); randn…

Django REST Framework视图

Django REST Framework (DRF) 视图类详解DRF 提供了丰富的视图类来构建 API,从基础到高级,满足不同复杂度的需求。以下是 DRF 的主要视图类及其使用场景:1. 基础视图类APIView所有 DRF 视图的基类,相当于 Django 的 View 类的增强…

Linux面试题及详细答案 120道(1-15)-- 基础概念

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs&…

week1-[分支结构]中位数

week1-[分支结构]中位数 题目描述 给定 444 个正整数 a,b,c,da,b,c,da,b,c,d,输出它们的中位数,答案四舍五入保留 111 位小数。 输入格式 输入共 111 行 444 个正整数 a,b,c,da,b,c,da,b,c,d。 输出格式 输出共 111 行 111 个浮点数表示答案。 样例 #1 样…

[激光原理与应用-259]:理论 - 几何光学 - 平面镜的反射、平面透镜的折射、平面镜的反射成像、平面透镜的成像的规律

一、平面镜的反射规律平面镜的反射遵循镜面反射定律,即光线在光滑表面(反射面平整度远大于波长)发生反射时,满足以下条件:反射光线、入射光线与法线共面:反射光线、入射光线和法线(垂直于反射面…

相机按键功能解析

相机按键功能解析佳能相机按键机身背面机身正面机身顶部机身侧面 佳能相机按键 机身背面取景器目镜:用于拍摄时观察相机形成的图像。实拍显示/视频拍摄按钮:按下即可开始拍摄或录制视频。光圈/曝光补偿键:调整光圈大小和曝光补偿,…

51单片机-驱动LED模块教程

本章思维导图: 51单片机驱动LED灯模块 LED灯元器件简介 LED(Light Emitting Diode,发光二极管) 是一种固态半导体器件,通过P-N结中电子与空穴复合直接将电能转化为光能。其核心结构由P型半导体(空穴主导&a…

Git 完全手册:从入门到团队协作实战(2)

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《C修炼之路》、《Linux修炼&#xff1a;终端之内 洞悉真理…

c语言中堆和栈的区别

1.栈区(stack):由编译器自动分配释放&#xff0c;栈主要用于存储局部变量、函数参数、函数调用和返回信息等。其操作方式类似于数据结构中的栈。 2.堆区(heap):一般由程序员分配释放&#xff0c;若程序员不释放&#xff0c;则可能会引起内存泄漏。注堆和数据结构中的堆栈不一样…

华为实验WLAN 基础配置随练

业务vlan 20 192.168.20.x管理vlan 100 192.168.100.x步骤① 网络互通Core sw:vlan batch 20 100 dhcp enable int vlanif 20IP add 192.168.20.1 24dhcp select interfaceinterface GigabitEthernet0/0/1/2port link-type trunkport trunk pvid vlan 100port trunk allow-pas…

CMake 如何查找 Python2和Python3

问题 在一个CMakeLists.txt文件里面看到了下面的这句话 find_package(Python2 COMPONENTS Interpreter Development NumPy)这个好有趣啊&#xff0c;Python2也是一个C的库吗&#xff0c;也有Python2Config.cmake或者FindPython2.cmake? 回答 find_package(Python2 COMPONENTS …

心灵笔记:刻意练习

心灵笔记&#xff1a;刻意练习提要 所有人都以为“杰出”源于“天赋”&#xff0c;而“天才”却说&#xff1a;我的成就源于“正确的练习”&#xff01; 定义&#xff1a;刻意练习是一种有目的、有方法、能带来能力持续提升的结构化训练方式&#xff0c;它并非简单的重复劳动&a…

langchain入门笔记03:使用fastapi部署本地大模型后端接口,优化局域网内的问答响应速度

文章目录前言一、fastapi的简单入门1&#xff1a;安装必要的包&#xff08;python3.11&#xff09;&#xff1a;2&#xff1a;快速搭建一个fastapi&#xff1a;二、提升问答的响应速度1. fastapi部署后端接口&#xff0c;在局域网内访问的方法2. 局域网内的测试&#xff1a;“未…

【CDA 新一级】学习笔记第1篇:数据分析的时代背景

作者&#xff1a;CDA持证人 张九领我们要学习数据分析&#xff0c;就要从当前时代的数据特点&#xff0c;找到在时代特点下企业需要数据分析的痛点&#xff0c;然后理解数据分析在企业中的作用。当前时代&#xff0c;数据分析的特征是哪些呢&#xff1f;我们用VUCA来概括数据分…