在早期经常遭到唾弃的就是在垃圾回收(下称:GC)机制中 STW(Stop-The-World)的时间过长。那么这个时候,我们又会好奇一点,作为 STW 的起始,Go 语言中什么时候才会触发 GC 呢?
1、什么是 GC
在计算机科学中,垃圾回收(GC)是一种自动管理内存的机制,垃圾回收器会去尝试回收程序不再使用的对象及其占用的内存。
John McCarthy Lisp
2、为什么要 GC
手动管理内存挺麻烦,管错或者管漏内存也很糟糕,将会直接导致程序不稳定(持续泄露)甚至直接崩溃。
3、GC 触发场景
GC 触发的场景主要分为两大类,分别是:
runtime.GC
3.1系统触发
src/runtime/mgc.go
gcTriggerHeap:gcTriggerTime:runtime.forcegcperiod gcTriggerCycle:
runtime.GC
3.2手动触发
runtime.GC
但我们要思考的是,一般我们在什么业务场景中,要涉及到手动干涉 GC,强制触发他呢?
debug
3.3 基本流程
runtime.GC
核心代码如下:
gcWaitOnMark
gcStart
gcWaitOnMark
sweepone Gosched
在本轮 GC 已经基本完成后,会调用 mProf_PostSweep 方法。以此记录最后一次标记终止时的堆配置文件快照。
结束,释放 M。
3.4 在哪触发
看完 GC 的基本流程后,我们有了一个基本的了解。但可能又有小伙伴有疑惑了?
本文的标题是 “GC 什么时候会触发 GC”,虽然我们前面知道了触发的时机。但是....Go 是哪里实现的触发的机制,似乎在流程中完全没有看到?
4、监控线程
(runtime)goroutine
代码如下:
forcegchelper goparkunlock goroutine
sysmon
gcTriggerTime now
forcegc.g forcegchelper
5、堆内存申请
在了解定时触发的机制后,另外一个场景就是分配的堆空间的时候,那么我们要看的地方就非常明确了。
mallocgc
nextFree
大对象:如果申请大于 32k 以上的大对象时,可能会触发 GC 行为。
总结
在这篇文章中,我们介绍了 Go 语言触发 GC 的两大类场景,并分别基于大类中的细分场景进行了一一说明。