GC简介
Go GC(Garbage Collection)垃圾回收是一种自动管理内存的方式.支持GC的语言无需手动管理内存,程序后台自动判断对象,是否存活并回收其内存空间,使开发人员从内存管理上解脱出来.
垃圾回收分类
- 引用计数 C++ std库,cocos2d
- 标记清楚
- 三色标记 go,
- 分代收集 java, .net
go使用的是三色标记
由来: 1959年,GC由John McCarthy 发明,用于Lisp中的手动内存管理,现在很多语言都提供了GC,不过GC的原理和基本算法并没有太大改变.
go GC的发展
Golang 早起版本GC问题可能较多,好在,每一个版本发布GC都有所改进
- 1.5版(2015.8)本之后,Go GC已经能满足大部分生产环境的使用要求; 加入了三色标记发,并发清除标记清除
- 1.8 (2017.2)通过混合写入屏障,使得STW(stop the world) 降到了sub ms; 增加了hybrid write barrier(混合写屏障)
Go GC特征
- 三色标记
- 并发标记和清扫
- 非分代
- 非紧缩
- 混合写屏障
三色标记
参考: https://en.wikipedia.org/wiki/Tracing_garbage_collection
- 程序开始时有黑白灰三个集合,初始时所有对象都是白色
- 从root对象开始标记,将所有可达对象标记为灰色
- 从灰色对象集合取出对象,将其引用对象标记为灰色,放入灰色集合,并将自己标记标记为黑色
- 重复第三步,直到灰色集合为空,即所有可达对象全部都被标记
- 标记结束后,不可达白色对象即为垃圾,对内存进行迭代清扫,回收白色对象
- 重置GC状态
写屏障
指针在赋值之前会开启写屏障;操作完成之后,关闭,回调之前的代码,保证垃圾回收机制完整,保证没有漏标记的对象;
三色状态
在GC中,并没有真正的三个集合来分别装三色对象;
go的想分配实在span中的,span里还有一个字段是gcmarkBits, mark阶段里面每个bit代表一个slot已被标记
白色对象该bit为0,灰色或者黑色为1(runtime.markBits); 白色会被回收
每个p中都有wbBuf和gcw gcWork,以及全局workbuf标记队列,实现生产者-消费者模型,在队列中的指针为灰色对象,表示已标记,待扫描