Telegram Channel
https://laisky.notion.site/Garbage-Collection-In-Go-Part-I-Semantics-500f4cd6c5a54eae9f455002d8c08d98?pvs=4

看到别人推荐的关于 Golang GC 的文,第一篇很有意思,后两篇有点水。

Golang 的 GC 使用三色标记法(tri-color),将所有的对方区分为 WHITE、GREY 和 BLACK 三色。BLACK 是需要保留的,GREY 是有待分拣,WHITE 就是可以清除的。

1. GC 启动后,将栈内所有的 root objects 都放进 GREY
2. 激活 write barrier,监听 GC 运行期间所有的写操作,将新的被引用对象放进 GREY
3. 遍历 GREY 中的对象,将其放入 BLACK。同时递归遍历这些对象所引用的子对象,也放进 BLACK。
4. 待 GREY 清空后,将 WHITE 中的对象清除。
https://pusher.github.io/tricolor-gc-visualization/

从 GC 的角度,可以分为三个步骤:

1. Mark Setup: 初始阶段,需要 STW,扫描所有的 root objects。
2. Marking: 遍历 GREY 的阶段,可以和用户程序并行执行。
3. Mark Termination: 最后阶段,需要 STW,清除 WHITE。

上面提到的 STW 就是 Stop The World,即暂停所有的用户程序,只执行 GC 相关的代码。这样虽然会导致用户程序的执行延迟,但是可以防止数据冲突。可以简单将其理解为全局锁。

Golang 给用户提供了两种微调 GC 的方式:

1. GOGC: 设置百分比,默认为 100,当内存翻倍时,触发下一次 GC。
2. GOMEMLIMIT: 设置堆内存峰值,当堆内存达到这个值时,触发下一次 GC。

通过微调这两个值,可以控制 GC 的频率。但是需要记住,微调 GC 的本质是在内存和 CPU 间进行 tradeoff。GC 对程序的延迟有两个部分:STW 的中断延迟、并行 SWEEP 期间占用 CPU 导致的性能下降。天下没有免费的午餐,增大 GC 的间隔并不会减少总延迟,非必要不用去调节这两个值。
 
 
Telegram Channel