go的垃圾回收器(GC)

Golang的GC算法主要是基于 标记-清扫(markandsweep)算法,此算法主要有两个主要的步骤:

标记(Mark phase)

清除(Sweep phase)

第一步,找出不可达的对象,然后做上标记。
第二步,回收标记好的对象。

传统mark and sweep算法在执行的时候,需要程序进程暂停!即 stop the world。
图解如下:
程序所有进程暂停,开始标记。
在这里插入图片描述
开始进行标记,process找出所有可达对象,并进行标记
在这里插入图片描述
标记完成后开始清除未标记的对象,即没有引用的对象
在这里插入图片描述
清理完成后,变成下图
在这里插入图片描述
最后,停止暂停,让程序继续跑。然后循环重复这个过程,直到process生命周期结束。

标记-清扫(Mark And Sweep)算法这种算法虽然非常的简单,但是还存在一些问题:

STW,stop the world;让程序暂停,程序出现卡顿。

标记需要扫描整个heap

清除数据会产生heap碎片

这里面最重要的问题就是:mark-and-sweep 算法会暂停整个程序。

Golang的解决方案是三色并发标记法

首先 ,程序创建的对象都标记成白色
在这里插入图片描述
从根出发扫描所有可达对象,标记为灰色,放入待处理队列。
在这里插入图片描述
从队列取出灰色对象,将其引用对象标记为灰色放入队列,自身标记为黑色,并放入黑色集合中。
在这里插入图片描述
重复从灰色队列取出数据,直到灰色对象队列为空。此时白色对象即为垃圾,进行回收。
在这里插入图片描述
此时,程序回收白色对象
在这里插入图片描述
最后,将所有黑色对象变为白色,重复上述过程,直至程序结束
在这里插入图片描述
gc和用户逻辑如何并行操作?
标记-清除(mark and sweep)算法的STW(stop the world)操作,就是runtime把所有的线程全部冻结掉,所有的线程全部冻结意味着用户逻辑是暂停的。这样所有的对象都不会被修改了,这时候去扫描是绝对安全的。

Go如何减短这个过程呢?标记-清除(mark and sweep)算法包含两部分逻辑:标记和清除。
我们知道Golang三色标记法中最后只剩下的黑白两种对象,黑色对象是程序恢复后接着使用的对象,如果不碰触黑色对象,只清除白色的对象,肯定不会影响程序逻辑。所以: 清除操作和用户逻辑可以并发。

标记操作和用户逻辑也是并发的,用户逻辑会时常生成对象或者改变对象的引用,那么标记和用户逻辑如何并发呢?

process新生成对象的时候,GC该如何操作呢?不会乱吗?
我们看如下图,在此状态下:process程序又新生成了一个对象,我们设想会变成这样:
在这里插入图片描述
但是这样显然是不对的,因为按照三色标记法的步骤,这样新生成的对象A最后会被清除掉,这样会影响程序逻辑。

Golang为了解决这个问题,引入了 写屏障这个机制。
写屏障:该屏障之前的写操作和之后的写操作相比,先被系统其它组件感知。
通俗的讲:就是在gc跑的过程中,可以监控对象的内存修改,并对对象进行重新标记。(实际上也是超短暂的stw,然后对对象进行标记)

在上述情况中, 新生成的对象,一律都标位灰色!即下图:
在这里插入图片描述
那么,灰色或者黑色对象的引用改为白色对象的时候,Golang是该如何操作的?
看如下图,一个黑色对象引用了曾经标记的白色对象。
在这里插入图片描述
这时候,写屏障机制被触发,向GC发送信号,GC重新扫描对象并标位灰色。
在这里插入图片描述
因此,gc一旦开始,无论是创建对象还是对象的引用改变,都会先变为灰色。
在这里插入图片描述
触发GC机制

  1. 在申请内存的时候,检查当前当前已分配的内存是否大于上次GC后的内存的2倍,若是则触发

  2. 监控线程发现上次GC的时间已经超过两分钟了,触发;

  3. 手动触发,调用 runtime.GC()

程序的优化

那么如何从代码方面优化以减少gc导致的STW的时间?

  1. 减少对象的分配

  2. 使用sync.Pool

说明

对于golang gc的时候,过程是:扫描-标记-清除,这3个步骤中在程序中能做的就是减少对象的分配,直观的结果就是减少了gc的扫描和标记时间,而我们已经知道mark阶段是会导致stw的,最终结果直接导致stw的时间减少。
sync.Pool有两个特性
2.1. 能有效分担对象存储压力
2.2. 对gc友好

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值