专栏首页Go语言指北Go高阶15,垃圾回收、三色标记原理,终于能跟面试官扯皮了!

Go高阶15,垃圾回收、三色标记原理,终于能跟面试官扯皮了!

垃圾回收(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)。这段时间程序会卡住。

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

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

对象 1、2、4 做上标记

  1. 清除未被标记的对象
  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;

  1. GC 开始扫描,从根节点开始遍历,发现只有 A 和 F 是根节点,于是将 A、F 从变为灰色对象。
  1. GC 继续扫描灰色对象,会将灰色对象的节点中引用的节点也变为灰色对象,A 节点引用的节点B、C、D 会被变为灰色对象,接着 A 的所有子节点遍历完毕,便会变为黑色对象,而 F 节点没有子节点,也会变为黑色对象。
  1. GC 会循环遍历灰色对象,直到灰色对象之中没有节点为止,在本例中,发现B、C、D 都没有子节点是白色,便将B、C、D 都变为黑色对象。
  1. 剩下E、G、H 为白色对象,GC 便进行回收这些白色对象。
  1. 上面的垃圾回收结束之后,GC 会在进行一步操作,也就是将黑色对象重新变色成白色对象,供下一次垃圾回收使用。

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性能测试和统计。

图片及部分相关技术知识点来源于网络搜索,侵权删!

参考文档

https://blog.csdn.net/zhghost/article/details/104120759

https://studygolang.com/articles/27243?fr=sidebar

http://idiotsky.top/2017/08/16/gc-three-color/

《GO专家编程》


有什么问题,可以公众号内回复或加我微信交流。

本文分享自微信公众号 - 微客鸟窝(gophpython),作者:有码无尘

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-09-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go垃圾回收 1:历史和原理

    新老朋友好久不见,我是大彬。今天为大家带来的分享是Go语言垃圾回收,这篇文章筹划的了很久,因为GC也是很强大的一个话题,关于GC已经有很多篇论文还有书籍,想通过...

    大彬
  • 图文结合,白话Go的垃圾回收原理

    前面两篇文章介绍了Go语言的内存分配策略以及Go协程动态扩充和收缩栈内存的原理,今天这篇文章我们主要来聊一下内存管理的另外一大块内容:垃圾回收。

    KevinYan
  • 深入理解Go GC

    GC(Garbage Collection)在计算机科学中是一种自动的存储器管理机制。当一个计算机上的动态存储器不再需要时,就应该予以释放,以让出存储器,这种存...

    咻咻ing
  • Go GC 20 问

    本文作者欧长坤,德国慕尼黑大学在读博士,Go/etcd/Tensorflow contributor,开源书籍《Go 语言原本》作者,《Go 夜读》SIG 成员...

    梦醒人间
  • 自动的内存管理系统实操手册——Golang垃圾回收篇

    ? 导语 | 现代高级编程语言管理内存的方式分自动和手动两种。手动管理内存的典型代表是C和C++,编写代码过程中需要主动申请或者释放内存;而PHP、Java ...

    腾小云
  • Go 内存管理 -- 垃圾回收

    go作为一个非常年轻的语言,吸取了各个语言的优点,比如说Java中优秀的垃圾回收,来释放程序员一部分精力。 本篇要说的就是垃圾回收,常见的垃圾回收算法有标记-...

    邹志全
  • 面试官:你说你熟悉jvm?那你讲一下并发的可达性分析

    那天刚刚下完雨,路过这个地方的时候,一瞬间就被这五颜六色的门板和自行车给吸引了,于是拍下了这张图片。看到这张图片的时候我就很开心,多鲜活、多舒服的画面呀。

    why技术
  • JVM 核心知识点

    想要提高程序员自身的内功心法无非就是: 数据结构跟算法 + 操作系统 + 网络 ,而所有的Java代码都是在JVM上运行的,了解了JVM好处就是:

    一个会写诗的程序员
  • 大吉大利 :空投十个JVM核心知识点,速度捡包

    想要提高程序员自身的内功心法无非就是数据结构跟算法 + 操作系统 + 计网 + 底层,而所有的Java代码都是在JVM上运行的,了解了JVM好处就是:

    sowhat1412
  • golang 系列:啥是垃圾回收?

    golang 的三色标记法虽然没有 java 的内存回收机制成熟,但它细分了回收过程,通过写屏障技术,能和用户程序并发进行,这也一定程度的提高了内存回收速度。

    lincoln
  • 学会清理坏情绪

    之前遇到一个客户,对各种广告文案和设计画面纠结万分,一个户外广告翻来覆去修改了无数次,拖了半年,连领导都换了,才最终定了最开始写的那句话,而那时候距离开盘已经不...

    用户1756920
  • GO GC 垃圾回收机制

    垃圾回收(Garbage Collection,简称GC)是编程语言中提供的内存管理功能。

    孤烟
  • 内存管理篇(三):Go垃圾回收之三色标记算法

    三色标记法(tricolor mark-and-sweep algorithm)是传统 Mark-Sweep 的一个改进,它是一个并发的 GC 算法,在Gola...

    灰子学技术
  • Go 垃圾回收

    Garbage Collection( GC )也就是垃圾回收到底是什么?内存空间是有限的,诸如变量等需要分配内存才能存储数据,而当这个变量不再使用的时候就需要...

    凌虚
  • 深入理解Nginx:java开发转游戏开发

    垃圾回收算法的实现设计到大量的程序细节,并且每一个平台的虚拟机操作内存的方式都有不同,所以不需要去了解算法的具体实现。

    云上之山
  • Go语言GC实现原理及源码分析

    在垃圾收集器开始工作时,从 GC Roots 开始进行遍历访问,访问步骤可以分为下面几步:

    luozhiyun
  • 内存管理设计精要

    持久存储的磁盘在今天已经不是稀缺的资源了,但是 CPU 和内存仍然是相对比较昂贵的资源,作者在 调度系统设计精要 中曾经介绍操作系统和编程语言对 CPU 资源的...

    labuladong
  • 一篇搞懂JAVA与GO垃圾回收

    导语 现代高级编程语言管理内存的方式分自动和手动两种。手动管理内存的典型代表是C和C++,编写代码过程中需要主动申请或者释放内存;而 PHP、Java 和 G...

    腾讯VTeam技术团队
  • golang 垃圾回收 gc

    摘要 在实际使用go语言的过程中,碰到了一些看似奇怪的内存占用现象,于是决定对go语言的垃圾回收模型进行一些研究。本文对研究的结果进行一下总结。 什么是垃圾回收...

    李海彬

扫码关注云+社区

领取腾讯云代金券