触发
- 调用 runtime.GC()
- 定时触发,该触发条件由
runtime.forcegcperiod变量控制,默认为 2 分 钟。当超过两分钟没有产生任何 GC 时,触发 GC - 根据内存分配阈值触发,该触发条件由环境变量GOGC控制,默认值为100(100%),当前堆内存占用是上次GC结束后占用内存的2倍时,触发GC
算法
标记-清除法
go V1.3以前的算法
过程:
- 暂停程序(stop the world)
- 标记所有可达的对象
- 清除不可达的对象
- 恢复程序
缺点:
- 程序需要暂停
- 需要扫描整个堆
- 可能产生堆碎片(堆数据不连续)
三色标记法
go V1.5的算法
过程:
- 扫描所有根节点,标记为灰色
- 将灰色对象引用的对象标为灰色,自身标为黑色(重复此步骤,直到没有引用)
- 回收白色对象
问题
-
没有STW,指针指向关系可能发生改变,可能有些对象被错误清除
- 白色被黑色引用;同时灰色丢了白色
-
屏障机制
解决
-
只要破坏上述问题的条件之一(满足下列条件之一)
- 强三色不变式:不允许黑色引用白色
- 弱三色不变式:黑色可引用白色,但白色必须被灰色引用或它的可达链路上游有灰色对象
实现强/弱三色不变式:屏障机制 堆上启用
-
插入屏障(满足强三色不变式)
-
对象被引用时触发:
- 堆上的对象引用新对象时,将新对象标记为灰色;
- 准备清除时,启动STW,将栈上的对象置为白色,重新扫描,将不可达对象回收,停止STW(因为栈对象可能也会引用新对象,但是用不了屏障机制,可能误删,所以需要该步骤)
-
不足:STW耗时
-
-
删除屏障(满足弱三色不变式)
-
对象被删除时触发:
- 将被删除的对象标为灰色
- 将灰色对象引用的对象标为灰色,自身标为黑色(重复此步骤,直到没有引用)
- 回收白色对象
-
不足:一个对象被删除了可以活过一轮,在下一轮被清理(因为该对象可能被其他对象引用)
-
混合屏障
过程:
- gc开始时将栈上的对象全部标为黑色,之后不再扫描(不用STW);gc期间栈上的新对象均标为黑色
- 被删除的对象标为灰色
- 被添加的对象标为灰色
调优
减少堆内存的分配;合理重复利用对象;避免string和byte[]之间的转化