跳到主要内容

GC 三色标记

问题

Go 的垃圾回收算法是什么?三色标记法如何工作?STW 停顿是多少?

答案

GC 发展历程

Go 版本GC 算法STW 停顿
Go 1.0标记-清扫(STW)数百 ms
Go 1.3并发标记数十 ms
Go 1.5三色标记 + 并发数 ms
Go 1.8三色标记 + 混合写屏障< 1ms
Go 1.12+持续优化通常 < 0.5ms

三色标记法

将堆上所有对象分为三种颜色:

  • 白色:未被访问,GC 结束后被回收
  • 灰色:已被访问,但其引用的对象还未全部扫描
  • 黑色:已被访问,其引用的对象也已全部扫描

标记过程:

  1. 初始化:所有对象标记为白色
  2. 从根出发:将根对象(全局变量、goroutine 栈)直接引用的对象标记为灰色
  3. 扫描灰色:取出一个灰色对象,将其引用的白色对象标记为灰色,然后将自身标记为黑色
  4. 重复步骤 3:直到没有灰色对象
  5. 清扫白色:剩余白色对象即为不可达对象,回收

并发标记的问题

GC 与用户代码并发执行时,可能出现漏标问题:

用户代码执行:黑色对象 A 新增引用白色对象 D
同时:灰色对象 B 删除了对 D 的引用
结果:D 已经不会被扫描到(B 不再引用 D,A 是黑色不会再扫描)
→ D 被错误回收!

写屏障(Write Barrier)解决这个问题——在指针赋值时通知 GC。

混合写屏障(Go 1.8+)

Go 1.8 采用混合写屏障(插入写屏障 + 删除写屏障的结合):

// 伪代码:每次指针写入时触发
func writePointer(slot *unsafe.Pointer, ptr unsafe.Pointer) {
// 标记被覆盖的旧指针指向的对象(删除写屏障)
shade(*slot)
// 标记新写入的指针指向的对象(插入写屏障)
shade(ptr)
// 实际写入
*slot = ptr
}

混合写屏障的优势:

  • 栈上操作不需要写屏障(栈对象会在 STW 时扫描)
  • STW 只需要两次极短停顿(开始标记 + 结束标记)

GC 完整流程

两次 STW 总共 < 1ms,大部分标记和清扫工作与用户代码并发执行。

GC 触发条件

触发方式条件
堆增长堆大小增长到上次 GC 后的 1 + GOGC/100
定时2 分钟没有 GC 时自动触发
手动runtime.GC() 强制触发

常见面试问题

Q1: Go GC 的 STW 时间是多少?

答案

Go 1.8+ 使用混合写屏障后,STW 只有两次极短停顿:

  • Mark Setup(开启写屏障):通常 < 0.2ms
  • Mark Termination(关闭写屏障):通常 < 0.1ms
  • 总 STW 通常 < 0.5ms,与堆大小无关

标记和清扫阶段都是并发执行的。

Q2: 为什么 Go 不用分代 GC?

答案

Java 的分代 GC 基于"大多数对象朝生夕灭"假设。Go 不用分代的原因:

  1. Go 的逃逸分析让短命对象留在栈上,堆上的对象本身就偏长命
  2. 分代 GC 需要写屏障追踪所有跨代指针引用(不只是 GC 期间),开销大
  3. Go 的并发三色标记 + 混合写屏障已经足够好

Q3: 三色标记的不变性是什么?

答案

三色不变性(Tri-color Invariant):黑色对象不能直接引用白色对象。

维护这个不变性就不会漏标。写屏障的目的就是在并发修改指针时维护三色不变性。

Q4: 写屏障有什么性能开销?

答案

写屏障只在 GC 标记阶段生效(通过全局标志位判断),未 GC 时无开销。GC 期间每次指针写入会多执行几条指令(检查标志 + shade),性能影响约 5~30%。Go 的混合写屏障不需要栈写屏障,减少了大量开销。

Q5: 如何观察 GC 行为?

答案

# 方法 1:环境变量
GODEBUG=gctrace=1 ./myapp

# 输出格式
# gc 1 @0.012s 2%: 0.018+1.2+0.025 ms clock, 0.14+0.35/1.0/0+0.20 ms cpu, 4->4->2 MB, 5 MB goal, 8 P
# gc 序号 @程序启动时间 GC占CPU%: STW1+并发标记+STW2 clock时间, CPU时间, 堆变化, 目标堆大小, P数量

# 方法 2:runtime.ReadMemStats
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("GC 次数: %d\n", m.NumGC)
fmt.Printf("堆大小: %d MB\n", m.HeapAlloc/1024/1024)

相关链接