Golang GC 演进之路

Golang GC 演进之路

前言:网上关于GC 的文章错综复杂,有的文章前后混乱,自相矛盾;有的文章讲的内容较为浅显,看完以后还是一脸懵,所以花了一周时间,翻阅了大量文章,结合runtime 下的GC源码,对关于GC的知识进行了一下整理,方便以后回顾:
个人更喜欢用Notion写文章
Notion文章链接 :Gc演进之路
如有错误之处,欢迎指点。

一、标记清除算法

在golang 1.3之前的时候主要用的普通的标记-清除算法,此算法主要有以下两个步骤:

  • 标记(Mark phase)
  • 清除(Sweep phase)
  • 具体步骤如下:
    1. 暂停业务逻辑(STW),分类出可达和不可达对象,做出标记
      在这里插入图片描述

      目前程序的可达对象有: 1-2-3 4-7 五个对象

    2. 开始标记,程序对所有可达的对象做上标记
      在这里插入图片描述

      1-2-3 4-7 等五个可达对象做上标记

    3. 标记完成后,清除所有未标记对象

      在这里插入图片描述

      对象 5 6 不可达,被GC 清除

    4. 关闭STW,恢复业务程序。然后循环重复这个过程,直到Process 程序生命周期结束。

整个流程非常简单,但是有一点需要额外注意:mark and sweep 算法在执行的过程中,需要暂停程序!即STW(stop the word) ,STW过程中,CPU不执行代码逻辑,全部用于垃圾回收,这个过程的影响很大,所以STW也是一些回收机制最大的难题和希望优化的点。

标记清除算法缺点:

  • STW,让整个程序暂停,程序会出现严重卡顿
  • 标记需要扫描整个heap
  • 清除数据会产生heap碎片

Go V1.3 变动

执行GC的基本流程首先就是启动STW,然后才进行标记清除,最后暂停STW,如下图:
在这里插入图片描述

从整个流程来看,全部的GC时间都是处在STW范围之内的,这样程序暂停的时间过长,影响程序的性能。所以在Go V1.3 做了简单的优化,将STW 的停止时间提前,这样能减少STW的时间范围,如图所示:
在这里插入图片描述

不论如何优化,这个版本的GC都会面临一个严重的问题,就是 Mark And Sweep 算法会暂停整个程序。为了面对并解决这个问题,在Go 1.5版本就采用 三色标记法 来优化这个问题。

二、三色标记法

Golang中的垃圾回收主要应用三色标记法,GC过程和其他用户goroutine可并发运行,但需要一定时间的STW,所谓的三色标记法实际上就是通过三个阶段的标记来确定需要清除的对象都有哪些。

  • 具体步骤如下:
    1. 所有新建对象,默认都标记为白色

      在这里插入图片描述

      上图所示,我们程序可抵达的内存对象关系如左图,右边的标记表,是用来记录目前每个对象的标记颜色分类的。这里面的 程序 指的是一些对象的根节点集合。所以如果我们将”程序” 展开来,会得到类似如下的表现形式:

      在这里插入图片描述

    2. 每次GC回收开始,会从根节点开始遍历所有对象,把遍历到的对象全部标记为灰色(放入灰色的集合)

      在这里插入图片描述

      遍历root根节点集合,标记可达的节点为灰色。(这里的遍历非递归遍历,只遍历一次根节点,如图所示,当前可达的对象是 对象1对象4,那么本轮遍历就结束了,对象1对象4 被标记为灰色,灰色表就会多出这两个对象)

    3. 遍历灰色集合,将灰色对象引用的对象标记为灰色,然后将灰色对象自身标记为黑色,如图所示:

      在这里插入图片描述

      这一次遍历只扫描灰色对象,将灰色对象可直接抵达的白色对象标记为灰色,移动到灰色表:如 对象2对象7 ,而之前的灰色 对象1对象4 则会被标记为黑色,由灰色表移动到黑色标记表中;

      这一步要循环进行,直到灰色标记表中没有灰色对象存在
      在这里插入图片描述

      重复上一步,直到灰色标记表中没有任何对象

      在这里插入图片描述

      当我们全部的可达对象都遍历后,将不再存在灰色对象,目前内存全部数据只有两种颜色,黑色和白色。黑色对象就是我们所有的可达对象,白色对象全部是不可达对象,所以白色对象就是目前内存中需要被清除的对象。

    4. 回收所有白色对象
      在这里插入图片描述

      将所有白色对象清除

以上就是 三色并发标记法,这里会有很多并发流程被扫描,执行并发流程的内存可能相互依赖,为了在GC过程中保证数据的安全,我们在开始三色标记之前就会进行STW,在扫描确定黑白对象之后暂停STW

很明显这样的GC扫描性

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂的程需猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值