golang 垃圾回收机制

Golang 垃圾回收

垃圾回收 (Garbage Collection, 简称 GC)是编程语言中自动的内存管理机制,清除不再使用的对象,释放对应内存

Golang GC 各版本变化

版本 GC 算法
v1.1 STW(stop the world)
v1.3 Mark STW,Sweep(标记清除)
v1.5 三色标记
v1.8 Hybrid wire barrier (三色标记基础加入写屏障)

标记清除算法(mark and sweep, v1.3)

    1. 找出不可达对象,mark
    1. 回收标记好的对象

mark and sweep 算法在执行的时候,需要程序暂停,即 stop the world

标记清除算法存在的问题

  • stop the world 程序会暂停,即程序会出现卡顿
  • 标记需要扫描整个堆(heap)
  • 清除数据会产生 heap 碎片

三色并发标记法(v 1.5)

该算法是在 v1.5 版本开始使用,这里的三色,对应垃圾回收过程中对象的三种状态:

  • 灰色:对象还在标记队列中等待
  • 黑色:对象已被标记,该对象不会在本次 GC 中被清理
  • 白色:对象未被标记,该对象将会在本次 GC 中被清理

三色标记法的过程(v1.5)

  1. 初始阶段,所有对象都是白色:

  2. GC 开始扫描,从根节点开始遍历,A 和 F 是根节点,将其标记为灰色对象, 即根节点先置灰。

  3. GC 继续扫描灰色对象,将根节点的子节点标记为灰色对象。A 的子节点 B C D 被标记为灰色对象,A 被标记为黑色对象。F 没有子节点,也被标记为黑色对象,即根节点置黑,子节点置灰

  4. GC 会循环遍历灰色对象,直到灰色对象之中没有节点结束。B、C、D没有子节点,会变为黑色对象,即循环遍历所有节点,将所有父节点置黑。

  5. 未被标记的 E、G、H 为白色对象,GC 便会回收这些白色对象,即回收未被标记的白色对象

  6. 这一轮垃圾回收结束后,GC 会进行进一步操作,将黑色对象重新变为白色对象,供下一次垃圾回收使用

垃圾回收优化-写屏障

STW (stop the world) 的目的是防止 GC 扫描时内存变化而停掉 goroutine, 而写屏障就是让 goroutine 与 GC 同时运行的手段
虽然写屏障不能完全消除 STW,但是可以大大减少 STW 的时间。写屏障类似一种开关,在 GC 的特定时间开启,开启后指针传递时会把指针标记,即本轮不回收,下次GC时再确定。
GC 过程中新分配的内存会被立即标记,用的并不是写屏障技术,也即 GC 过程中分配的内存不会在本轮 GC 中回收。

垃圾回收优化-Mutator-Assist

为防止内存分配过快、在 GC 执行过程中,如果 goroutine 需要分配内存,那么这个 goroutine 会参与一部分 GC 的工作,这个机制叫做 Mutator Assist。

垃圾回收触发机制

  1. 每次内存分配时都会检查当前内存分配量是否 已经到达阈值,如果达到就立即启动 GC。内存增长率由环境变量GOGC 控制,默认是 100,即每当内存扩大一倍时启动 GC。
    之后堆内存达到上一次垃圾手机的 2 倍才会触发 GC.

  2. 默认情况下,最长 2 分钟触发一次 GC。

  3. 程序代码中也可以使用 runtime.GC() 来手动触发 GC。这主要用于 GC 性能测试和统计。

-------------THANKS FOR READING-------------