引用自《Go GC 20 问》https://mp.weixin.qq.com/s/o2oMMh0PF5ZSoYD0XOBY2Q
GarbageCollection 垃圾回收,一种自动内存管理机制
根集合,在GC时最先检查,包括:
全局变量
执行栈
寄存器
标记清理:从根对象触发,标记清扫可回收的对象
标记整理:为了解决内存碎片,将对象尽可能整理到一块连续内存
标记与清扫分批进行,每次执行一小部分,增量推进,达到实时、无停顿的目的
增量整理:在增量式基础上增加对象整理过程
根据对象存活时间长短分类,时间短倾向于被回收,存活时间长的倾向于不回收
引用计数:引用计数值归零则立即回收
无分代、不整理、并发的三色标记法
对象整理目的:
核心:三色对象以及波面推进
当垃圾回收开始时,只有白色对象。随着标记过程开始进行时,灰色对象开始出现(着色),这时候波面便开始扩大。当一个对象的所有子节点均完成扫描时,会被着色为黑色。当整个堆遍历完成时,只剩下黑色和白色对象,这时的黑色对象为可达对象,即存活;而白色对象为不可达对象,即死亡。这个过程可以视为以灰色对象为波面,将黑色对象和白色对象分离,使波面不断向前推进,直到所有可达的灰色对象都变为黑色对象为止的过程。
是指在垃圾回收过程中为了保证实现的正确性、防止无止境的内存增长等问题而不可避免的需要停止赋值器进一步操作对象图的一段过程。
例如启动一个routine运行无限for循环,其他逻辑代码执行runtime.GC()时,会一直卡在STW阶段
如今的STW停顿时间优化在半毫秒之内了,GC进入STW时需要等待让所有用户态代码停止,但是for{}所在的routine永远“不会被中断”从而停留在STW阶段。
实践中某一个routine长时间不停止,强制拖慢STW
但是go 1.14之后,这类的goroutine可以被异步的停止
在GC语言中常说的内存泄漏:预期很快要被释放的内存,由于附着在长期存活的内存上、或者生命周期意外的延长,导致预计可以回收的内存无法被正常回收
用户态代码在回收过程中会并发更新对象,所以就有了写屏障、混合写屏障。
什么时候会破坏垃圾回收的正确性?
只要避免任意条件,则不会出现对象丢失:
条件1被避免,所有白色对象均被灰色对象引用,白色对象不会被遗漏
条件2被避免,即使白色对象被写入黑色对象中,但是从灰色对象出发总存在一条没有被访问过的路径,从而找到白色对象
在STW阶段对象赋值器触发写屏障,刷新对象。。。太复杂建议看原文。
Go 1:串行三色标记清扫
Go 1.3:并行清扫,标记过程需要 STW,停顿时间在约几百毫秒
Go 1.5:并发标记清扫,停顿时间在一百毫秒以内
Go 1.6:使用 bitmap 来记录回收内存的位置,大幅优化垃圾回收器自身消耗的内存,停顿时间在十毫秒以内
Go 1.7:停顿时间控制在两毫秒以内
Go 1.8:混合写屏障,停顿时间在半个毫秒左右
Go 1.9:彻底移除了栈的重扫描过程
Go 1.12:整合了两个阶段的 Mark Termination,但引入了一个严重的 GC Bug 至今未修(见问题 20),尚无该 Bug 对 GC 性能影响的报告
Go 1.13:着手解决向操作系统归还内存的,提出了新的 Scavenger
Go 1.14:替代了仅存活了一个版本的 scavenger,全新的页分配器,优化分配内存过程的速率与现有的扩展性问题,并引入了异步抢占,解决了由于密集循环导致的 STW 时间过长的问题
详细查看:https://www.codercto.com/a/99611.html
runtime.GC:手动触发 GC
runtime.ReadMemStats:读取内存相关的统计信息,其中包含部分 GC 相关的统计信息
debug.FreeOSMemory:手动将内存归还给操作系统
debug.ReadGCStats:读取关于 GC 的相关统计信息
debug.SetGCPercent:设置 GOGC 调步变量
debug.SetMaxHeap(尚未发布):设置 Go 程序堆的上限值
主动调用:runtime.GC触发,阻塞式调用等待GC运行完毕
被动触发:使用系统监控,2分钟没有产生GC则强制触发
使用步调算法,核心思想是控制内存增长比例
###Go语言GC流程
1、GCMark:标记准备阶段,为并发标记做准备,启动写屏障。赋值器状态:STW
gcBgMarkPrepare
2、GCMark:扫描标记阶段,与赋值器并发执行,写屏障开启。赋值器状态:并发
gcBgMarkRootPrepare
3、GCMarkTermination:标记终止阶段,保证一个周期内标记任务完成。赋值器状态:STW
gcBgMarkTinyAllocs
4、GCoff:内存清扫阶段,将需要回收的内存还到堆中,写屏障关闭。赋值器状态:并发
gcBgMarkWorker
5、GCoff:内存归还阶段,将过多的内存还给操作系统,写屏障关闭。赋值器状态:并发
gcBgMarkDone
gcBgMarkTermination