GC的方式

理解垃圾回收算法 一文里面有gif的形式,直观地描述了常用的gc算法

引用计数

  • 不足的地方,每次都要对对象进行计数,开销比较大
  • 会导致循环引用;A引用了B,B也引用了A,那此时就无法进行gc
  • 并且会造成大量的碎片

标记清除

  • 标记清除每次都需要STW,是对整个内存进行清除,所以性能不是很好

三色标记

  • 三色指
    • 白色:无引用(可以被清除的对象)
    • 黑色:当前对象及子对象都存在引用,被标记(一定不会被清理的对象)
    • 灰色:子对象未被标记(本次不确定,下一次再判断一次,是黑还是白)
  • 三色标记的问题在于如果确定一个对象是灰色,若gc刚走完,此时已经被标记为白色的对象,添加了一个引用,此时就会错误地gc掉,同时gc的标记也是全局的,最早的版本是没有优化,导致性能很差;优化后,标记与运行态是同时进行的,不影响代码逻辑;
  • 那如何解决上面的实时地判断被标记为白色的对象,突然有了一个引用呢?就需要引用到写屏障

写屏障(write Barrier)

GC触发条件

  • gcTriggerAlways: 强制触发GC
  • gcTriggerHeap: 当前分配的内存达到一定值就触发GC
  • gcTriggerTime: 当一定时间没有执行过GC就触发GC
  • gcTriggerCycle: 要求启动新一轮的GC, 已启动则跳过, 手动触发GC的runtime.GC()会使用这个条件

函数入口

// src/runtime/mgc.go method gcStart
func gcStart(mode gcMode, trigger gcTrigger) {
}

参考