前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go: 垃圾回收策略

go: 垃圾回收策略

作者头像
运维开发王义杰
发布2023-08-16 20:19:38
1750
发布2023-08-16 20:19:38
举报
文章被收录于专栏:运维开发王义杰

在 Go 中,使用的垃圾回收(GC)策略是 Concurrent Mark-Sweep(CMS)。这是一种基于分代的、并发的、并行的垃圾回收器,设计上考虑到了低延迟、高吞吐量和尽可能小的暂停时间。

Go 的 GC 由两个主要阶段组成:标记(Mark)阶段和清扫(Sweep)阶段。

  1. 标记阶段(Mark Phase):这个阶段的目的是找到堆中所有还活跃的对象。这个过程分为三个子阶段:开始标记(Mark Setup)、并发标记(Concurrent Mark)和标记终止(Mark Termination)。
    • 开始标记(Mark Setup):这是一个非常短的“Stop The World”(STW)阶段,所有的 goroutines 都会暂停执行。在这个阶段,GC 会设置一些必要的参数,然后启动后台的并发标记 goroutine。
    • 并发标记(Concurrent Mark):在这个阶段,后台的 goroutine 会并发地对堆中的对象进行标记,同时前台的 goroutine 也会继续执行,修改堆上的数据。并发标记阶段会追踪和标记所有从根对象(例如全局变量和当前活动的 goroutine 栈)直接或间接引用的对象。
    • 标记终止(Mark Termination):这是第二个“Stop The World”(STW)阶段。在这个阶段,所有的 goroutines 都会再次暂停执行。GC 会完成最后的标记工作,处理并发标记阶段中遗漏的对象,并为下一阶段的清扫做好准备。
  2. 清扫阶段(Sweep Phase):在这个阶段,GC 会清理掉那些在标记阶段中被标记为“非活动”的对象,回收这些对象占用的内存。清扫阶段是并发执行的,也就是说,GC 会在后台清理对象,而前台的 goroutine 会继续执行,可能创建新的对象。

在 Go 中,垃圾回收器还使用了一种叫做“分代回收”(Generational GC)的优化技术。简单来说,这种技术的思想是,新创建的对象更有可能在短时间内变得非活动,因此应该更频繁地对它们进行回收。在每次 GC 后,Go 会标记出那些有对象被分配但是没有被清理的内存区域,然后在下一次 GC 时优先对这些区域进行标记和清扫。

触发GC

Go的垃圾回收并不是定时触发的,它的触发时机主要取决于内存的分配情况。Go使用的是一个基于分配的触发机制,而不是基于时间的触发机制。

当你的程序分配的内存超过一定阈值时,垃圾回收器就会触发。这个阈值是由上一次垃圾回收之后的存活对象数量计算出来的。具体来说,如果上次垃圾回收结束后,存活对象占用的内存大小为X,那么当新分配的内存加上X达到2X时,就会触发新的垃圾回收。

换句话说,垃圾回收的触发是基于堆的增长速率的。如果你的程序持续分配新的内存但不释放旧的内存,垃圾回收会更频繁地触发。反之,如果你的程序的内存分配速率较低,或者分配的内存很快就被释放,垃圾回收就不会那么频繁地触发。

需要注意的是,虽然这是Go的默认行为,但是你可以通过调用runtime.GC()函数来手动触发垃圾回收。此外,你还可以通过调整GOGC环境变量来改变垃圾回收的触发频率,例如,设置GOGC=200(这是默认值)表示当堆的大小增长到上次垃圾回收后的两倍时触发垃圾回收,设置GOGC=100则表示当堆的大小增长到上次垃圾回收后的一倍时触发垃圾回收。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维开发王义杰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档