理解Golang的GOGC
Clement
5 min read·Sep 18, 2022
互联网上的中文资源对GOGC的介绍多面向面试,没能形象地解答为什么我们需要这个环境变量。
我想尝试通过画图,用更直观的方式阐释GOGC的作用。
为什么我们需要GOGC?
垃圾回收的触发时机对我们的App有何影响?
以上是我们需要GOGC的原因,它可以帮助我们实现以下目标:
然而,这两个目标是相互制约的:
APP占用尽量少的内存 ≠ APP拥有尽量多的CPU时间
GOGC的作用就是平衡这个关系:
当GOGC取值过小时:
当GOGC取值过大时:
更具体地说GOGC改变了下图
中的GC trigger位置:
如何优化Golang的垃圾回收?
一些文章热心地指导读者"优化Golang垃圾回收",但是读者能做的事情只有:
runtime.SetGCPercent()除非修改Golang的源码,否则Golang的垃圾回收没有优化的空间。开发者通常没有精力或能力去优化它,只需要在CPU利用率和内存占用之间做出权衡,选择一个合适的GOGC值。
Go 1.19引入了GOMEMLIMIT环境变量,它为App设置了一个软上限(soft limit),虽然称为"上限" ,但当App内存超过这个"上限"时,App并不会被Go runtime杀掉,依然有可能因为申请内存失败被操作系统杀掉。
可以这样理解GOMEMLIMIT的作用:
当App内存接近GOMEMLIMIT时,垃圾回收会更频繁地运行,尽量将内存限制在GOMEMLIMIT之下(不保证做到)。
从效果上看,当App内存接近GOMEMLIMIT时,GOGC仿佛被动态地设置为更小的值。
那么如何控制App运行时的内存硬上限呢?在容器盛行的时代,只需控制容器的内存,例如:
docker run --memory=2g /bin/app