gc

214 阅读2分钟

触发

  • 调用 runtime.GC()
  • 定时触发,该触发条件由 runtime.forcegcperiod 变量控制,默认为 2 分 钟。当超过两分钟没有产生任何 GC 时,触发 GC
  • 根据内存分配阈值触发,该触发条件由环境变量GOGC控制,默认值为100(100%),当前堆内存占用是上次GC结束后占用内存的2倍时,触发GC

算法

标记-清除法

go V1.3以前的算法

过程:

  • 暂停程序(stop the world)
  • 标记所有可达的对象
  • 清除不可达的对象
  • 恢复程序

缺点:

  • 程序需要暂停
  • 需要扫描整个堆
  • 可能产生堆碎片(堆数据不连续)

三色标记法

go V1.5的算法

过程:

  • 扫描所有根节点,标记为灰色
  • 将灰色对象引用的对象标为灰色,自身标为黑色(重复此步骤,直到没有引用)
  • 回收白色对象

问题

  • 没有STW,指针指向关系可能发生改变,可能有些对象被错误清除

    • 白色被黑色引用;同时灰色丢了白色
  • image-20230524201615211

屏障机制

解决

  • 只要破坏上述问题的条件之一(满足下列条件之一)

    • 强三色不变式:不允许黑色引用白色
    • 弱三色不变式:黑色可引用白色,但白色必须被灰色引用或它的可达链路上游有灰色对象

实现强/弱三色不变式:屏障机制 堆上启用

  • 插入屏障(满足强三色不变式)

    • 对象被引用时触发:

      • 堆上的对象引用新对象时,将新对象标记为灰色;
      • 准备清除时,启动STW,将栈上的对象置为白色,重新扫描,将不可达对象回收,停止STW(因为栈对象可能也会引用新对象,但是用不了屏障机制,可能误删,所以需要该步骤)
    • 不足:STW耗时

  • 删除屏障(满足弱三色不变式)

    • 对象被删除时触发:

      • 将被删除的对象标为灰色
      • 将灰色对象引用的对象标为灰色,自身标为黑色(重复此步骤,直到没有引用)
      • 回收白色对象
    • 不足:一个对象被删除了可以活过一轮,在下一轮被清理(因为该对象可能被其他对象引用)

混合屏障

过程:

  • gc开始时将栈上的对象全部标为黑色,之后不再扫描(不用STW);gc期间栈上的新对象均标为黑色
  • 被删除的对象标为灰色
  • 被添加的对象标为灰色

调优

减少堆内存的分配;合理重复利用对象;避免stringbyte[]之间的转化