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()强制触发

相关推荐
我的div丢了肿么办1 天前
go语言中管道 channel的使用
后端·go
海宇数科1 天前
Go数据工程:利用海宇婚恋风险报告优化实名制严肃婚恋交友合规体验
人工智能·go
用户125758524361 天前
Golang Web后台管理框架推荐:Gin、GoFrame与数据面板项目怎么分
go
我的div丢了肿么办1 天前
进程和线程以及go语言中的协程
后端·go
福兮说2 天前
Go time 包的九个坑:== 判断相等、Parse 差 8 小时、1 月 31 日加一个月变成 3 月 3 日
go
我的div丢了肿么办3 天前
go语言中的空接口和类型断言
后端·go
Thinker QAQ3 天前
并发编程(七):volatile——从语言规则到 CPU
java·python·go·并发编程·volatile·memory model
ZealSinger3 天前
Go1.25 FlightRecorder慢请求截trace
网络·数据库·go
福兮说3 天前
Go 迭代器的七个坑:break 后 panic、一次性迭代器、iter.Pull 不 stop,还有一个跑错地方的 defer
go
ThinkerQAQ_3 天前
并发编程(七):volatile——从语言规则到 CPU
java·python·go