Go Runtime(五):GC、写屏障与Pacer
本文源码基线为 Go 1.26.2、Linux/amd64、默认 GOEXPERIMENT。该版本的实验 baseline 已默认启用 Green Tea GC,即 goexperiment.GreenTeaGC == true;可用 GOEXPERIMENT=nogreenteagc 构建旧标记路径。两条路径共享 GC 阶段、根扫描、写屏障、assist、pacer 和 sweep,本篇会明确指出默认 Green Tea 特有的 span 批处理。 gctrace 中的 STW 暂停可能很短,请求尾延迟却仍会在分配突增时升高。原因是 GC 成本不只来自暂停,还包括并发标记占用的 CPU、分配 goroutine 承担的 assist,以及为目标堆大小预留的内存。 Go GC 的核心不是“三色”这个名词,而是在用户 goroutine 持续修改对象图时,怎样并发找出仍然可达的对象,并把这些暂停、CPU 与内存成本控制在目标范围内。本文从“什么条件触发一轮 GC”开始,沿同一轮周期解释工作由谁完成,以及这些成本最终在哪里被程序观察到。 一轮 GC 可以理解为四套机制协作:标记算法判断对象生死,写屏障维护并发正确性,分配 goroutine 通过 assist 偿还标记债务,pacer 控制何时开始以及投入多少资源。 模型与触发 为什么需要GC 函数返回只能自然回收栈帧,无法决定堆对象是否仍被其他对象引用: GOtype Node struct { next *Node } func newNode() *Node { return &Node{} } 对象可能通过全局变量、其他堆对象、goroutine 栈或 runtime 结构继续可达。GC 必须从一组根出发遍历引用图,未被发现的堆对象才可以回收。 ...