本文档描述了 Go 的垃圾回收器(GC),它会自动回收不再使用的对象所占用的内存。Go GC 是一个并发的、三色标记清除收集器,旨在在生产环境中提供低延迟和可预测的暂停时间。
有关内存管理和分配的详细信息,请参阅内存管理。
Go 垃圾回收器具有以下特点:
GC 周期分为几个不同的阶段,这些阶段协同工作,在最大限度地减少对正在运行的程序干扰的同时回收未使用的内存。
来源:src/runtime/mgc.go5-119 src/runtime/proc.go211-212
Go 垃圾回收器遵循三色标记抽象,并分阶段运行。
gcphase 设置为 _GCmarkgcphase 设置为 _GCmarkterminationgcphase 设置为 _GCoff 并禁用写屏障来源:src/runtime/mgc.go24-82 src/runtime/mgc.go210-243 src/runtime/mgcscavenge.go6-18
垃圾回收器使用三色标记抽象
算法如下:
写屏障通过将黑色对象引用的白色对象标记为灰色来保护“没有黑色对象指向白色对象”的不变量。
来源:src/runtime/mgcmark.go16-60 src/runtime/mbitmap.go5-54
写屏障对于并发收集器正确工作至关重要。它确保 GC 不会错过在并发标记期间变得可达的任何对象。
写屏障:
写屏障实现在 src/runtime/writebarrier.go 中,并由 writeBarrier.enabled 标志控制,该标志在标记阶段(_GCmark 和 _GCmarktermination)设置为 true。
来源:src/runtime/mgc.go215-232 src/runtime/runtime2.go102-108
Go 垃圾回收器使用调度算法来决定何时启动 GC 周期,平衡内存使用与 CPU 开销。
GC 可由多种条件触发:
runtime.GC()环境变量 GOGC 控制 GC 目标
GOGC=100 且堆使用 4MB,则 GC 将在堆达到 8MB 时触发GOGC=off 禁用自动垃圾回收GC 调度算法:
来源:src/runtime/mgc.go112-118 src/runtime/mgcpacer.go15-57
Go GC 通过几种机制实现低延迟的并发标记
gcBackgroundUtilization 控制(默认为 GOMAXPROCS 的 25%)来源:src/runtime/mgc.go213-243 src/runtime/mgcpacer.go15-57 src/runtime/mgcmark.go16-128
标记完成后,GC 在清除阶段回收内存
Go 中的清除分两个方面进行:
mcentral.cacheSpan 同步驱动sweepone 异步驱动这两种算法最终都调用 mspan.sweep,该函数清除单个堆 span。
来源:src/runtime/mgcsweep.go5-52 src/runtime/mheap.go57-99
理解内存管理结构有助于理解 GC 的工作原理
来源:src/runtime/mheap.go56-176 src/runtime/malloc.go17-61 src/runtime/mbitmap.go5-54
GOGC 进行调整gcBackgroundUtilization 控制)GOGC 值会降低 CPU 开销,但会增加内存使用量GOGC=100)来源: src/runtime/mgcpacer.go15-45 src/runtime/mgc.go112-118
GOGC:设置垃圾收集目标百分比(默认值:100)GOMEMLIMIT:设置 GC 将尝试遵守的软内存限制GODEBUG=gctrace=1:将 GC 相关信息输出到 stderrruntime.GC():强制进行垃圾回收debug.SetGCPercent():在运行时更改 GC 目标百分比runtime.ReadMemStats():获取内存分配统计信息runtime/metrics 包提供详细的 GC 指标来源: src/runtime/mgcpacer.go18-45 src/runtime/mgc.go464-486 src/runtime/export_test.go243-244
Go 的垃圾收集器设计旨在提供可预测、低延迟的垃圾收集,并具有合理的内存开销。其并发设计允许应用程序代码在垃圾收集周期中以最小的干扰运行,使其适用于对延迟敏感的应用程序。
GC 的设计侧重于简单性和可预测性,而不是榨取最后一丁点的性能,这符合 Go 使编程更轻松、更富有成效同时仍然能提供良好性能的理念。