0、各个版本机制
相关概念
- 垃圾回收
- 内存管理
- 自动释放
- 三色标记法
- STW(stop the world)
GO v1.3及之前GC - 标记清除法
- STW:强制暂停当前程序的所有逻辑业务。
- 标记清除(mark and sweep):执行STW,遍历对所有的可达对象做上标记,(可达对象:通过该程序创建、调用和依赖的对象,不包括依赖该程序中对象的对象),剩余不可达的对象(即未标记的对象)清除。
- 缺点:会使用STW,让程序暂停,性能低,程序卡顿;标记需要扫描整个heap,复杂度高;会产生heap碎片,随后的碎片清理问题。
GO v1.5改进GC - 三色标记法
- 三个标记表:White白色标记表、Gray灰色标记表、Black黑色标记表,初始所有对象都记录在White.
- 遍历第一层:对程序的Root Set根节点集合进行遍历,只遍历一层,将遍历到的对象从White中取出,存入Gray.
- 遍历Gray标记表:将Gray中的所有对象遍历一层,遍历后将结果对象加入Gray,并将原本Gray中的对象加入Black.
- 循环往复遍历Gray,直至Gray 中无对象,此时White中的所有对象都可作为Garbage。.
STW的必要性(在三色标记法中)
- 存在的隐患:在整个GC过程中,若不使用STW时,同时满足两个条件,可能会造成对象丢失。
- 条件1:Black中的对象引用了一个White中的对象,比如对象C.
- 条件2:GC过程中,Gray中的对象舍弃了对于White中特定对象的引用,比如对象C.
1、Golang采用的优化方法
强三色不变式
- 破坏条件1:强制性的不允许Black中对象引用White中对象。
弱三色不变式
- 破坏条件2:Black对象可以引用White对象,但此White对象必须存在其他Gray对其引用,或者可达此White对象的链路上上游存在Gray对象。
2、实现方法 - 屏障机制
插入屏障
- 机制:在Black对象A引用新的对象B时,对象B立马被标记为Gray,即将对象B挂在对象A的下游。(满足强三色不变式)
- 不足:插入屏障不可以用于栈空间,只对位于堆空间的对象执行插入屏障机制,所以每次结束时,需要使用STW机制重新扫描栈空间的对象,大约需要10~100ms.(满足弱三色不变式)
删除屏障
- 机制:被删除的对象,如果自身为Gray or White,那么被标记为Gray.
- 不足:回收精度较低,通过删除屏障存活下的对象可以多活一轮,当然,到了下一轮GC如果其没什么变化,依旧会被删除。
3、混合写屏障
机制
- GC开始,对栈上所有对象扫描并标记为黑色(之后不再进行第二次重复扫描,无需STW)。
- GC期间,任何在栈上创建的新对象,均标记为黑色。
- GC期间,被删除的对象标记为灰色;被添加的对象标记为灰色(在栈空间上不启用)。
场景一
- 场景内容:对象A被一个堆对象B删除引用,成为栈对象C的下游。
- 场景结果:对象A标记为Gray.
场景二
- 场景内容:对象A被一个栈对象B删除引用,成为另一个栈对象C的下游。
- 场景结果:对象A标记为Black.
场景三
- 场景内容:对象A被一个堆对象B删除引用,成为另一个堆对象C的下游。
- 场景结果:对象A标记为Gray.
场景四
- 场景内容:对象A被一个栈对象B删除引用,成为另一个堆对象C的下游。
- 场景结果: 对象A依旧标记为Black,堆对象C的最相邻下游节点标记为Gray.