gc

gc是和内存分配紧密相关的,golang中堆区是按照class size进行划分,共定义了67种class。
在1.10版本中,堆区是连续的,分为spans、bitmap和arena三部分。其中arena就是按照class size进行划分的。
由于堆区的空间划分(bitmap和class size),这决定了gc需要使用非移动式的算法,golang采用mark and sweep算法。
mark:通过可达性分析标记对象是否存活,即是否存在一条从根对象到目的对象的引用链。
因为在mark阶段中修改对象的引用关系可能会产生错误的标记,导致sweep阶段回收存活对象,通过stop the world这种简单的方案可以避免这个问题。
因此golang早期版本mark and sweep 2个阶段都是stop the world。
而由于sweep阶段是回收死亡对象的,不会影响程序的运行,回收代码是可以和应用代码并行执行的。
又优化为在mark阶段stop the world,sweep阶段不需要stw。
但是stw会影响应用代码的执行,导致程序卡顿,吞吐量下降等问题。
因此优化的地方就是在于如何避免stw或者减少stw的时间。
随着版本迭代,mark算法又变为三色标记算法。
三色标记的过程为,首先,开始阶段,所有对象都是白色,遍历根集合对象,将遍历到的对象标记为灰色。遍历灰色对象,将灰色对象引用的对象标记为灰色,自身标记为黑色。重复上一步的操作,即遍历灰色对象,直到没有灰色对象为止。这时只有白色对象和黑色对象,白色对象即要回收的对象。
在标记阶段,如果修改了对象的引用关系,可能会导致错误标记。比如在遍历灰色对象时,由于修改了引用关系,导致原来由灰色对象引用的白色对象变为由黑色对象引用,即删除了原来灰色对象到白色对象的引用。因为不会再次遍历黑色对象,所以这个白色对象将会被回收。
简单的解决方案就是标记时stop the world,但是这样导致三色标记相对于以前的标记算法没有任何优势。而产生问题的根源在于,标记期间黑色对象引用了白色对象,且破坏了灰色对象到白色对象间的引用关系。如果可以解决这个问题,标记是不需要stw的。
解决方法:
(1)不允许黑色对象引用白色对象
(2)允许黑色对象引用白色对象,但白色对象必须处于灰色保护状态,即存在灰色对象到白色对象的引用关系
其中(1)满足强三色不变式,(2)满足弱三色不变式。
对应的实现方案是插入屏障和删除屏障。
插入屏障:A引用B时,B标记为灰色。满足强三色不变式。
删除屏障:被删除的对象,如果为白色,则标记为灰色。满足弱三色不变式。

根对象:不需要经过其他对象就可以直接访问到的对象
(1)goroutine栈空间和全局栈空间/栈中的对象,包括gc前正在执行的方法中的局部变量等
(2)全局变量/静态变量

gc的详细过程见 gc过程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值