Go 语言,垃圾回收原理

简介: 垃圾回收(Garbage Collection,简称GC)是编程语言中自动的内存管理机制,垃圾回收,垃圾指的是不再需要的内存块,如果不及时清理就没有办法再利用。

垃圾回收(Garbage Collection,简称GC)是编程语言中自动的内存管理机制,垃圾回收,垃圾指的是不再需要的内存块,如果不及时清理就没有办法再利用。

垃圾回收算法

常见的垃圾回收算法有:

  • 引用计数:每个对象维护一个引用计数,如果这个对象被销毁,则计数 -1 ,当计数为 0 时,回收该对象。
  • 优点:对象可以很快被回收,不会出现内存耗尽或到达阀值才回收。
  • 缺点:不能很好的处理循环引用
  • 标记-清除:从根变量开始变量所以引用的对象,引用的对象标记“被引用”,没有被标记的则进行回收。
  • 优点:解决了引用计数的缺点。
  • 缺点:需要 STW(stop the world),暂时停止程序运行。
  • 分代收集::按照对象生命周期长短划分不同的代空间,生命周期长的放入老年代,短的放入新生代,不同代有不同的回收算法和回收频率。
  • 优点:回收性能好
  • 缺点:算法复杂

Go 语言的 GC(垃圾回收)

标记-清除(mark and sweep)

此算法是在Go V1.3 之前使用的,主要有两个主要的步骤:

标记(Mark phase)——》清除(Sweep phase)

  1. 暂停程序业务逻辑, 找出不可达的对象,然后做上标记。

注意:mark and sweep 算法在执行的时候,需要程序暂停!也就是所谓的 STW(stop the world)。这段时间程序会卡住。

image.png

程序可达对象为 1、2、4

  1. 开始标记,找出所有可达的对象,并标记

image.png

对象 1、2、4 做上标记

  1. 清除未被标记的对象

image.png

  1. 程序暂停取消。然后重复上面的过程,直至程序生命周期结束。

三色并发标记法

此算法是在Go V1.5 开始使用的,三色只是为了叙述上方便抽象出来的一种说法,实际上对象并没有颜色之分。这里的三色,对应了垃圾回收过程中对象的三种状态:

  • 灰色:对象还在标记队列中等待
  • 黑色:对象已被标记,该对象不会在本次GC中被清理
  • 白色:对象未被标记,该对象将会在本次GC中被清理
  1. 初始状态下所有对象都是白色的。
  2. 从根节点开始遍历所有对象,把遍历到的对象变成灰色对象(备注:这里变成灰色对象的都是根节点的对象)。
  3. 遍历灰色对象,将灰色对象引用的对象(备注:这里指的是灰色对象引用到的所有对象,包括灰色节点间接引用的那些对象)也变成灰色对象,然后将遍历过的灰色对象变成黑色对象。
  4. 循环步骤3,直到灰色对象全部变黑色。
  5. 通过写屏障(write-barrier)检测对象有变化,重复以上操作(备注:因为 mark 和用户程序是并行的,所以在上一步执行的时候可能会有新的对象分配,写屏障是为了解决这个问题引入的)。
  6. 收集所有白色对象(垃圾)。

举例说明:

  1. 初识阶段,所以对象均为白色,调用情况为:

root ->A->B/A->C/A<->D;

root->F;

E;

G->H;

image.png

  1. GC 开始扫描,从根节点开始遍历,发现只有 A 和 F 是根节点,于是将 A、F 从变为灰色对象。

image.png

  1. GC 继续扫描灰色对象,会将灰色对象的节点中引用的节点也变为灰色对象,A 节点引用的节点B、C、D 会被变为灰色对象,接着 A 的所有子节点遍历完毕,便会变为黑色对象,而 F 节点没有子节点,也会变为黑色对象。

image.png

  1. GC 会循环遍历灰色对象,直到灰色对象之中没有节点为止,在本例中,发现B、C、D 都没有子节点是白色,便将B、C、D 都变为黑色对象。

image.png

  1. 剩下E、G、H 为白色对象,GC 便进行回收这些白色对象。

image.png

  1. 上面的垃圾回收结束之后,GC 会在进行一步操作,也就是将黑色对象重新变色成白色对象,供下一次垃圾回收使用。

image.png

Stop The World

Golang 中的 STW(Stop The World)是停掉所有的 goroutine,专心做垃圾回收,待垃圾回收结束后再恢复 goroutine。 STW 时间的长短直接影响了应用的执行,时间过长对于一些web 应用来说是不可接受的,这也是广受诟病的原因之一。 为了缩短 STW 的时间,Golang 不断优化垃圾回收算法,这种情况得到了很大的改善。

垃圾回收优化

写屏障(Write Barrier)

STW 目的是防止 GC 扫描时内存变化而停掉 goroutine,而写屏障就是让 goroutine 与GC同时运行的手段。 虽然写屏障不能完全消除STW,但是可以大大减少STW的时间。 写屏障类似一种开关,在 GC 的特定时机开启,开启后指针传递时会把指针标记,即本轮不回收,下次 GC 时再确定。 GC 过程中新分配的内存会被立即标记,用的并不是写屏障技术,也即GC过程中分配的内存不会在本轮GC中回收。

辅助GC(Mutator Assist)

为了防止内存分配过快,在 GC 执行过程中,如果 goroutine 需要分配内存,那么这个 goroutine 会参与一部分GC的工作,即帮助 GC 做一部分工作,这个机制叫作 Mutator Assist。

垃圾回收触发时机

  1. 每次内存分配时都会检查当前内存分配量是否已达到阀值,如果达到阀值则立即启动 GC。内存增长率由环境变量 GOGC 控制,默认为100,即每当内存扩大一倍时启动GC。
    阀值 = 上次GC内存分配量 * 内存增长率
  2. 默认情况下,最长2分钟触发一次GC。
  3. 程序代码中也可以使用 runtime.GC() 来手动触发GC。这主要用于GC性能测试和统计。
相关文章
|
1天前
|
Java 编译器 Go
探索Go语言的性能优化技巧
在本文中,我们将深入探讨Go语言的底层机制,以及如何通过代码层面的优化来提升程序性能。我们将讨论内存管理、并发控制以及编译器优化等关键领域,为你提供一系列实用的技巧和最佳实践。
|
1天前
|
Cloud Native Go API
Go语言在微服务架构中的创新应用与实践
本文深入探讨了Go语言在构建高效、可扩展的微服务架构中的应用。Go语言以其轻量级协程(goroutine)和强大的并发处理能力,成为微服务开发的首选语言之一。通过实际案例分析,本文展示了如何利用Go语言的特性优化微服务的设计与实现,提高系统的响应速度和稳定性。文章还讨论了Go语言在微服务生态中的角色,以及面临的挑战和未来发展趋势。
|
1天前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
1天前
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
|
2天前
|
运维 Go 开发者
Go语言在微服务架构中的应用与优势
本文深入探讨了Go语言在构建微服务架构中的独特优势和实际应用。通过分析Go语言的核心特性,如简洁的语法、高效的并发处理能力以及强大的标准库支持,我们揭示了为何Go成为开发高性能微服务的首选语言。文章还详细介绍了Go语言在微服务架构中的几个关键应用场景,包括服务间通信、容器化部署和自动化运维等,旨在为读者提供实用的技术指导和启发。
|
2天前
|
安全 Go 调度
探索Go语言的并发之美:goroutine与channel
在这个快节奏的技术时代,Go语言以其简洁的语法和强大的并发能力脱颖而出。本文将带你深入Go语言的并发机制,探索goroutine的轻量级特性和channel的同步通信能力,让你在高并发场景下也能游刃有余。
|
3天前
|
安全 Go 调度
探索Go语言的并发模型:Goroutine与Channel的魔力
本文深入探讨了Go语言的并发模型,不仅解释了Goroutine的概念和特性,还详细讲解了Channel的用法和它们在并发编程中的重要性。通过实际代码示例,揭示了Go语言如何通过轻量级线程和通信机制来实现高效的并发处理。
|
8天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
29 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
1月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
16天前
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
40 0