Golang底层原理剖析之垃圾回收GC(一)

简介: Golang底层原理剖析之垃圾回收GC(一)

前置知识

概念了解

Root set根节点就是发现堆内存可达数据的一组起点,一般为bss段、数据段以及协程栈对应的元数据

GC用来清理堆,为什么还要扫描栈?因为栈上的对象会引用堆上的对象

Go V1.3-标记清除法

  • 标记(Mark phase)
  • 清除(Sweep phase)

步骤

  1. 暂停程序的正常执行流程(开始STW)
  2. 从Root Set根节点出发找出所有可达对象
  3. 给所有可达对象坐上标记
  4. 开始清除未标记的不可达对象
  5. 恢复程序的正常执行流程(停止STW)

缺点

  1. STW,stop the world;让程序暂停,程序出现卡顿 (重要问题)
  2. 标记需要扫描整个heap
  3. 清除数据会产生heap碎片

Go V1.5-三色标记法

三色标记法实际上就是通过三个阶段的标记来确定清楚的对象都有哪些

步骤

  1. 暂停程序的正常执行流程(开始STW)
  2. 只要是新创建的对象,默认为白色
  3. GC开始时,从根节点开始遍历所有对象,把遍历到的第一层对象从白色变为灰色
  4. 遍历一次灰色集合,将灰色对象引用的对象变为灰色,把原来灰色对象变为黑色
  5. 重复第3步骤,直到没有灰色对象
  6. 回收所有白色对象,白色对象没有被任何引用,也就是垃圾
  7. 恢复程序的正常执行流程(停止STW)

图示

去除STW的三色标记法的图示

不难看出,我们上面已经清楚的体现三色的特性。但是这里面可能会有很多并发流程均会被扫描,执行并发流程的内存可能相互依赖,为了在GC过程中保证数据的安全,我们在开始三色标记之前就会加上STW,在扫描确定黑白对象之后再放开STW。但是很明显这样的GC扫描的性能实在是太低了。

那么Go是如何解决标记-清除(mark and sweep)算法中的卡顿(stw,stop the world)问题的呢?

我们加入如果没有STW,那么也就不会再存在性能上的问题,那么接下来我们假设如果三色标记法不加入STW会发生什么事情?

去除STW的三色标记法产生的问题

最后我们才发现,本来是对象4合法引用的对象3,却被GC给“误杀”回收掉了。

可以看出,有两种情况,在三色标记法中,是不希望被发生的。

  1. 一个白色对象被黑色对象引用(白色被挂在黑色下)
  2. 灰色对象与它之间的可达的白色对象遭到破坏(灰色同时丢了该白色)

==如果当以上两个条件同时满足时,就会出现对象丢失现象! ==

并且,如图所示的场景中,如果示例中的白色对象3还有很多下游对象的话, 也会一并都清理掉。

为了防止这种现象的发生,最简单的方式就是STW,直接禁止掉其他用户程序对对象引用关系的干扰,但是STW的过程有明显的资源浪费,对所有的用户程序都有很大影响。那么是否可以在保证对象不丢失的情况下合理的尽可能的提高GC效率,减少STW时间呢?答案是可以的,我们只要使用一种机制,尝试去破坏上面的两个必要条件就可以了。

Go V1.8-三色标记+混合写屏障

“强-弱” 三色不变式

我们让GC回收器,满足下面两种情况之一时,即可保对象不丢失。 这两种方式就是“强三色不变式”和“ 弱三色不变式”

强三色不变式

强三色不变式:强制性的不允许黑色对象引用白色对象(不存在黑色对象引用到白色对象的指针)

这样就不会出现有白色对象被误删的情况

弱三色不变式

弱三色不变式:黑色对象可以引用白色对象,但是这个白色对象必须存在其他灰色对象对它的引用,或者可达它的链路上游存在灰色对象

所有被黑色对象引用的白色对象都处于灰色保护状态

两种屏障方式

为了遵循上述的两个方式,GC算法演进到两种屏障方式,分别为“插入写屏障”, “删除写屏障”。

使用了插入写屏障或者删除写屏障的三色标记法,可以大幅减少STW的时间。

插入写屏障

介绍

行为->插入写屏障:在A对象引用B对象的时候,B对象被标记为灰色。(将B挂在A下游,B必须被标记为灰色)

满足->强三色不变式. (不存在黑色对象引用白色对象的情况了, 因为白色会强制变成灰色)

注:栈空间的特点是容量小,但是要求相应速度快,因为函数调用弹出频繁使用, 所以“插入写屏障”机制,对于栈中的对象是不生效的,“插入写屏障” 仅仅使用在堆中生效。所以在结束时需要STW来重新扫描栈,执行三色标记法回收白色垃圾,这次STW大约的时间在10~100ms间。

插入写屏障不对栈生效!插入写屏障不对栈生效!插入写屏障不对栈生效!

图示

当全部三色标记扫描之后,栈上有可能依然存在白色对象被引用的情况(如上图的对象9). 所以要对栈重新进行三色标记扫描, 但这次为了对象不丢失, 要对本次标记扫描启动STW暂停. 直到栈空间的三色标记结束.

最后将栈和堆空间 扫描剩余的全部白色节点清除. 这次STW大约的时间在10~100ms间

Golang底层原理剖析之垃圾回收GC(二):https://developer.aliyun.com/article/1417146


目录
相关文章
|
8月前
|
Prometheus 监控 算法
CMS圣经:CMS垃圾回收器的原理、调优,多标+漏标+浮动垃圾 分析与 研究
本文介绍了CMS(Concurrent Mark-Sweep)垃圾回收器的工作原理、优缺点及常见问题,并通过具体案例分析了其优化策略。重点探讨了CMS的各个阶段,包括标记、并发清理和重标记
CMS圣经:CMS垃圾回收器的原理、调优,多标+漏标+浮动垃圾 分析与 研究
|
8月前
|
存储 算法 Java
G1原理—5.G1垃圾回收过程之Mixed GC
本文介绍了G1的Mixed GC垃圾回收过程,包括并发标记算法详解、三色标记法如何解决错标漏标问题、SATB如何解决错标漏标问题、Mixed GC的过程、选择CollectSet的算法
G1原理—5.G1垃圾回收过程之Mixed GC
|
6月前
|
缓存 算法 Java
JVM深入原理(八)(一):垃圾回收
弱引用-作用:JVM中使用WeakReference对象来实现软引用,一般在ThreadLocal中,当进行垃圾回收时,被弱引用对象引用的对象就直接被回收.软引用-作用:JVM中使用SoftReference对象来实现软引用,一般在缓存中使用,当程序内存不足时,被引用的对象就会被回收.强引用-作用:可达性算法描述的根对象引用普通对象的引用,指的就是强引用,只要有这层关系存在,被引用的对象就会不被垃圾回收。引用计数法-缺点:如果两个对象循环引用,而又没有其他的对象来引用它们,这样就造成垃圾堆积。
172 0
|
6月前
|
算法 Java 对象存储
JVM深入原理(八)(二):垃圾回收
Java垃圾回收过程会通过单独的GC线程来完成,但是不管使用哪一种GC算法,都会有部分阶段需要停止所有的用户线程。这个过程被称之为StopTheWorld简称STW,如果STW时间过长则会影响用户的使用。一般来说,堆内存越大,最大STW就越长,想减少最大STW,就会减少吞吐量,不同的GC算法适用于不同的场景。分代回收算法将整个堆中的区域划分为新生代和老年代。--超过新生代大小的大对象会直接晋升到老年代。
129 0
|
8月前
|
存储 监控 架构师
ZGC圣经:ZGC垃圾回收器的原理、调优,ZGC 漏标的 分析与 研究
ZGC圣经:ZGC垃圾回收器的原理、调优,ZGC 漏标的 分析与 研究
|
8月前
|
存储 缓存 算法
G1原理—3.G1是如何提升垃圾回收效率
本文深入探讨了G1垃圾回收器提升GC效率的核心机制,包括记忆集(RSet)、位图(BitMap)和卡表(CardTable)的设计与作用。记忆集通过记录跨代引用避免了不必要的老年代遍历,位图用于高效描述内存使用状态以优化标记过程,而卡表则在节约记忆集内存的同时提供更详细的引用信息。此外,文章还解析了DCQ(Dirty Card Queue)和DCQS(Dirty Card Queue Set)机制如何异步更新RSet,确保在高并发场景下的性能与准确性。这些设计共同提升了G1在标记、清理及整理内存时的效率。
324 10
|
8月前
|
存储 算法 Java
G1原理—6.G1垃圾回收过程之Full GC
本文详细探讨了G1垃圾回收器对Full GC(FGC)的优化处理,涵盖FGC的前置处理、整体流程及并行化改进。重点分析了传统FGC串行化的局限性以及G1通过Region分区和RSet机制实现并行标记的优势,包括任务窃取提升效率、跨分区压缩以生成空闲Region等技术细节。此外,文章还介绍了G1的新特性——字符串去重优化,通过判断char数组一致性减少重复字符串占用内存,从而提升内存使用效率。总结部分全面回顾了G1在FGC中的各项优化措施及其带来的性能改善。
G1原理—6.G1垃圾回收过程之Full GC
|
8月前
|
存储 算法 Java
G1原理—4.G1垃圾回收的过程之Young GC
本文详细解析了G1垃圾回收器中YGC(Young Generation Collection)的完整流程,包括并行与串行处理阶段。内容涵盖YGC相关参数设置、YGC与Mixed GC及FGC的关系、新生代垃圾回收的具体步骤(如标记存活对象、复制到Survivor区、动态调整Region数量等),以及并行阶段的多线程操作和串行阶段的关键任务(如处理软引用、整理卡表、重构RSet)。
G1原理—4.G1垃圾回收的过程之Young GC
|
11月前
|
算法 网络协议 Java
【JVM】——GC垃圾回收机制(图解通俗易懂)
GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)
|
存储 安全 测试技术
GoLang协程Goroutiney原理与GMP模型详解
本文详细介绍了Go语言中的Goroutine及其背后的GMP模型。Goroutine是Go语言中的一种轻量级线程,由Go运行时管理,支持高效的并发编程。文章讲解了Goroutine的创建、调度、上下文切换和栈管理等核心机制,并通过示例代码展示了如何使用Goroutine。GMP模型(Goroutine、Processor、Machine)是Go运行时调度Goroutine的基础,通过合理的调度策略,实现了高并发和高性能的程序执行。
666 29

推荐镜像

更多