golang gc笔记

GC

三色标记法过程

  1. 开始前所有对象都是白色

  2. 将根节点指向的对象标记成灰色

  3. 遍历每个灰色对象,将自己指向的对象标成灰色,同时将自己标成黑色

  4. 重复至没有灰色对象

  5. 清除剩余的所有白色对象

写屏障

因为标记过程是并发的,在并发阶段新创建的对象如何处理着色?

  1. 白色,不行,万一引用这个新对象的是个黑色,那在这一轮标记结束后,该对象会被清除,可能会引起用户程序错误

  2. 灰色,可行,染成灰色是偏保守但不会出错的方案,但如果这个对象实际上不是存活对象的话,这轮gc是肯定不会清除他的,只能等下一轮gc

  3. 黑色,不行,万一新对象引用了一个白对象,该白对象就可能不会被扫描到,该白对象会被清除,可能会引起用户程序错误 (存疑?这么说对不对?)

完整过程

标记准备

  1. stw

  2. 所有处理器都会进入安全点

标记

  1. 将gc状态改为_GCmark,在堆上开启写屏障,栈上不启用,将根对象扫描任务入队(包括栈对象、全局对象以及不在堆中的运行时数据结构)

  2. 恢复程序执行(/usr/local/go/src/runtime/mgc.go:1381)

  3. 遍历根节点扫描任务队列,扫描goroutine栈时会导致goroutine停止,并将栈上的所有指针置灰(/usr/local/go/src/runtime/mgcmark.go:1485)

  4. 遍历灰色队列,将灰色置为黑色,并将其指向的对象置灰

  5. 分布式终止算法检测是否标记完毕

标记结束

  1. stw,将gc状态改为_GCmarktermination

  2. 关闭工作线程、协助线程

清除

  1. 将gc状态改为_GCoff,初始化清理状态并关闭写屏障(/usr/local/go/src/runtime/mgc.go:280 setGCPhase)

  2. 恢复程序执行

  3. 后台并发清理所有内存管理单元,在申请内存时才会惰性回收内存

stop the world -> 修改屏障 -> start the world

混合写屏障

特点:

  1. 写屏障只应用在堆上启用,栈上不启用。

  2. GC期间新分配的对象为黑色。

  3. 被删除和被添加的对象均标记为灰色。

好处:

  • 降低了标记终止状态的stw时间

关于协助线程

默认gc会遵从用户设置的gc消耗cpu上限,但如果用户内存分配过快,导致gc不过来时,gc会通过抢占goroutine来主动抢占cpu使用量,选择goroutine的原则是:谁分配的快就抢占谁

触发时机

后台触发

runtime会在程序初始化时开启一个goroutine用来定时强制触发gc

用户手动触发

用户手动调用runtime.GC()

申请内存时触发

申请内存时根据堆大小触发垃圾收集

参考文章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值