golang的垃圾回收

垃圾回收的几种机制

引用计数

过程:

1)当对象被创建时,初始化计数器为1

2)当更新指针时,新指向的对象引用计数加一,旧对象引用计数减一,如果为0则回收掉,放入空闲队列,并且递归的去 更新

优点:

1)实时性高,当对象引用计数为0时,立即回收

2)垃圾回收过程中应用无需挂起

缺点:

1)指针的更新需要手动的去操作,当前对象的引用计数为0时,需要递归更新对象的引用计数

2)无法解决循环引用问题(自循环引用、相互循环引用、多循环引用)

解决循环引用的方法:

1)避免产生循环引用

2)在合适的时机,手动显示的断开

3)弱引用 weak_ptr

标记清除

从root开始一层层扫描,root指当前所有goroutine的栈和全局数据区的变量(主要是这两个)

扫描过程中把所有可达的object标记出来,未被标记的object就需要清除,清除后的object会被放回到mcache中以备后续分配使用

整个过程需要stop the worl,挂起所有用户goroutine

三色标记

对于黑色的object,如果标记期间发生了写操作,写屏障会在真正赋值前将新对象标记为灰色

标记过程中,新分配的object,会先被标记成黑色再返回

对上的object被赋值给一个栈上的指针,写屏障是检测不到的,所以标记的最后阶段,还会回头重新扫描一下所有的栈空间,确保没有遗漏

混合写屏障

不需要最后回头重新扫描所有goroutine的栈空间了,是的整个GC过程中的stw可以忽略不计了

但也带来一些代价,如果C未被赋值给L,却被置灰,只能等下一次GC的时候再进行回收

还有一种情况,当GC过程中新创建的对象(被置黑),也会被下次回收

节点复制

分代收集(新生代和老年代)

将堆划分为两个多个称为代的空间,新创建的对象放在新生代中,随着垃圾回收的重复执行,生命周期长的对象会被提升到老年代中

golang的GC

1)1.3版本以前,go runtime在一定条件下(内存超过阈值或定期2min)暂停所有任务的执行,进行mark&sweep操作,操作完成后启动所有任务的执行,整个过程需要stw,挂起所有goroutine

2)1.3版本开始,go runtime分离了mark和sweep操作,也是先暂停所有任务执行并启动mark,mark完之后就重新启动被暂停的任务,让sweep任务和普通协程任务一样并行的一起执行。如果运行在多核处理器上,go会试图让gc任务放到单独的核心上运行,尽量不影响业务代码的执行,标记过程stw,清除过程并行

3)1.4版本,runtime很多代码取代了原生的c语言,采用go语言实现

4)1.5版本,三色标记清除垃圾收集器(非分代的、非移动的、并发的),三色标记法的mark操作是可以渐进执行的,而不需要每次都扫描整个内存空间,可以减少stop the world的时间,三色标记+写屏障

5)1.8版本,Hibrid write Barrier(混合写屏障),不需要最后回头重新扫描所有goroutine的栈空间

GC何时被触发

1)堆上内存达到一定数值

2)每隔2min,强制触发

3)用户手动触发,使用runtime.GC()强制触发

相关推荐
一丝晨光1 天前
数值溢出保护?数值溢出应该是多少?Swift如何让整数计算溢出不抛出异常?类型最大值和最小值?
java·javascript·c++·rust·go·c·swift
陌尘(MoCheeen)2 天前
技术书籍推荐(002)
java·javascript·c++·python·go
白泽来了4 天前
字节大模型应用开发框架 Eino 全解(一)|结合 RAG 知识库案例分析框架生态
开源·go·大模型应用开发
致于数据科学家的小陈4 天前
Go 层级菜单树转 json 处理
python·go·json·菜单树·菜单权限·children
白总Server6 天前
Golang领域Beego框架的中间件开发实战
服务器·网络·websocket·网络协议·udp·go·ssl
ん贤6 天前
GoWeb开发
开发语言·后端·tcp/ip·http·https·go·goweb
纪元A梦6 天前
华为OD机试真题——荒岛求生(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现
java·c语言·javascript·c++·python·华为od·go
chxii9 天前
3.2goweb框架GORM
go
42fourtytoo10 天前
从0开始建立Github个人博客(hugo&PaperMod)
运维·服务器·python·go·github
xuhe211 天前
[tldr] GO语言异常处理
go·error