Treasure / Go GC分析

Created Sat, 26 Feb 2022 00:00:00 +0000
654 Words

如何启用GC跟踪

GODEBUG=gctrace=1 go run *.go

其中 gctrace=1 表示只针对这个进程进行GC追踪

标记流程

go采用三色标记法,主要是为了提高并发度,这样扫描过程可以拆分为多个阶段,而不用一次扫描全部

  • 黑 根节点扫描完毕,子节点也扫描完毕

  • 灰 根节点扫描完毕,子节点未扫描

  • 白 未扫描

扫描是从 .bss .data goroutine栈开始扫描,最终遍历整个堆上的对象树

标记 mark

标记过程是一个广度优先的遍历过程,扫描节点,将节点的子节点推送到任务队列中,然后递归扫描子叶节点,直到所有工作队列被排空

mark阶段会将白色对象标记,并推入队列中变为灰色

memory barrier

保障了代码描述中对内存的操作顺序,即不会在编译期被编译器进行调整,也不会在运行时被CPU的乱序执行所打乱

write barrier

在应用进入 GC 标记阶段前的 stw 阶段,会将全局变量 runtime.writeBarrier.enabled 修改为 true,这时所有的堆上指针修改操作在修改之前便会额外调用 runtime.gcWriteBarrier

由于GC和Go主程序并发执行,所以必须要在扫描时监控内存可能出现的状态改变,所以需要写屏障,所以需要暂停GO主程序(STW)

hybrid wirte barrier (after go1.8)

改方式的基本思想是:对正在被覆盖的对象进行着色,且如果当时栈未扫描完成,则同样对指针进行着色

GC流程

程序启动会为每个P分配一个 mark worker 来标记内存,负责为进入STW做前期工作

  • 起初认为所有 object 都被认定为白色
  • 但栈,堆和全局变量的object被标记为灰色

GC会将灰色object标记为黑色,将灰色object所包含的所有指针所指向的地址都标记为灰色,递归这两个步骤,最终对象非黑即白,其中白色object即未被引用且可以被回收,如果object标记为no scan,则递归结束,标记为黑色

todo https://blog.csdn.net/asd1126163471/article/details/124113816