go内存逃逸和GC(垃圾回收)工作原理

news/2025/1/23 2:00:59/

go内存逃逸和GC(垃圾回收)工作原理

在go语言中,编译器通过逃逸分析决定变量的内存分配位置,这直接影响着程序的性能和内存使使用效率,

逃逸分析

Go逃逸分析最基本的原则是:如果一个函数返回对一个变量的引用,那么它就会发生逃逸。

任何时候,一个值被分享到函数栈帧范围之外,它都会在堆上被重新分配。

Go 语言GC(垃圾回收)的工作原理

答案

最常见的垃圾回收算法有标记清除(Mark-Sweep) 和引用计数(Reference Count),Go 语言采用的是标记清除算法。并在此基础上使用了三色标记法和写屏障技术,提高了效率。

标记清除收集器是跟踪式垃圾收集器,其执行过程可以分成标记(Mark)和清除(Sweep)两个阶段:

  • 标记阶段 — 从根对象出发查找并标记堆中所有存活的对象;
  • 清除阶段 — 遍历堆中的全部对象,回收未被标记的垃圾对象并将回收的内存加入空闲链表。

标记清除算法的一大问题是在标记期间,需要暂停程序(Stop the world,STW),标记结束之后,用户程序才可以继续执行。为了能够异步执行,减少 STW 的时间,Go 语言采用了三色标记法。

三色标记算法将程序中的对象分成白色、黑色和灰色三类。

  • 白色:不确定对象。
  • 灰色:存活对象,子对象待处理。
  • 黑色:存活对象。

标记开始时,所有对象加入白色集合(这一步需 STW )。首先将根对象标记为灰色,加入灰色集合,垃圾搜集器取出一个灰色对象,将其标记为黑色,并将其指向的对象标记为灰色,加入灰色集合。重复这个过程,直到灰色集合为空为止,标记阶段结束。那么白色对象即可需要清理的对象,而黑色对象均为根可达的对象,不能被清理。

三色标记法因为多了一个白色的状态来存放不确定对象,所以后续的标记阶段可以并发地执行。当然并发执行的代价是可能会造成一些遗漏,因为那些早先被标记为黑色的对象可能目前已经是不可达的了。所以三色标记法是一个 false negative(假阴性)的算法。

三色标记法并发执行仍存在一个问题,即在 GC 过程中,对象指针发生了改变。比如下面的例子:

A (黑) -> B (灰) -> C (白) -> D (白)

正常情况下,D 对象最终会被标记为黑色,不应被回收。但在标记和用户程序并发执行过程中,用户程序删除了 C 对 D 的引用,而 A 获得了 D 的引用。标记继续进行,D 就没有机会被标记为黑色了(A 已经处理过,这一轮不会再被处理)。

A (黑) -> B (灰) -> C (白) 

D (白)

为了解决这个问题,Go 使用了内存屏障技术,它是在用户程序读取对象、创建新对象以及更新对象指针时执行的一段代码,类似于一个钩子。垃圾收集器使用了写屏障(Write Barrier)技术,当对象新增或更新时,会将其着色为灰色。这样即使与用户程序并发执行,对象的引用发生改变时,垃圾收集器也能正确处理了。

一次完整的 GC 分为四个阶段:

  • 1)标记准备(Mark Setup,需 STW),打开写屏障(Write Barrier)
  • 2)使用三色标记法标记(Marking, 并发)
  • 3)标记结束(Mark Termination,需 STW),关闭写屏障。
  • 4)清理(Sweeping, 并发)
  • 参考 fullstack

参考内容:

Golang内存逃逸是什么?怎么避免内存逃逸?

逃逸分析对性能的影响

一文搞懂七种基本的GC垃圾回收算法


http://www.ppmy.cn/news/1565359.html

相关文章

【服务器报错】libGL.so.1: cannot open shared object file:

libGL.so.1: cannot open shared object file 错误表明系统无法找到或加载 OpenGL 库文件 libGL.so.1。这个问题可能出现在不同的场景中,例如当您尝试运行图形应用程序或模拟器时。以下是一些解决方案,您可以根据具体情况尝试: sudo apt ins…

【MySQL】MySQL连接池原理与简易网站数据流动是如何进行

MySQL连接池原理与简易网站数据流动是如何进行 1.MySQL连接池原理2.简易网站数据流动是如何进行 点赞???收藏???关注??? 你的支持是对我最大的鼓励,我们一起努力吧??? 1.MySQL连接池原理 目前我们对mysql有了一定的理解,下面我们谈一下&am…

机器学习-核函数(Kernel Function)

核函数(Kernel Function)是一种数学函数,主要用于将数据映射到一个更高维的特征空间,以便于在这个新特征空间中更容易找到数据的结构或模式。核函数的主要作用是在不需要显式计算高维特征空间的情况下,通过内积操作来实…

STL—stack与queue

目录 Stack stack的使用 stack的模拟实现 queue queue的使用 queue的模拟实现 priority_queue priority_queue的用法 priority_queue的模拟实现 容器适配器 种类 Stack http://www.cplusplus.com/reference/stack/stack/?kwstack stack是栈,后入先出 stack的…

什么是 Java 虚拟机(JVM)?

Java虚拟机(JVM)是Java平台的核心组件,它是一个抽象的计算机,用于执行Java字节码。以下是关于JVM的详细介绍: 一、基本概念 字节码与JVM的关系 当Java源代码(.java文件)被编译后,会…

Linux下PostgreSQL-12.0安装部署详细步骤

一、安装环境 postgresql-12.0 CentOS-7.6 注意:确认linux系统可以正常连接网络,因为在后面需要添加依赖包。 二、pg数据库安装包下载 下载地址:PostgreSQL: File Browser 选择要安装的版本进行下载: 三、安装依赖包 在要安…

从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CICD)

从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CI/CD) 目录 项目初始化:构建一个简单的 Node.js 应用设置 Docker 环境:容器化你的应用配置 CI/CD:自动化构建与部署上线前的最后检查:…

从零开始打造一个Java基于 Spring Boot 的旅游信息化平台

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…