Go是一种垃圾回收语言:
http://golang.org/doc/go_faq.html#garbage_collection
这里说它是标记-清除垃圾回收器,但没有深入探讨细节,并且正在研究替代方案……然而,自从Go发布以来,这段文字似乎并没有更新。
它仍然是标记-清除吗?它是保守式还是精确式的?它是分代的吗?
Go是一种垃圾回收语言:
http://golang.org/doc/go_faq.html#garbage_collection
这里说它是标记-清除垃圾回收器,但没有深入探讨细节,并且正在研究替代方案……然而,自从Go发布以来,这段文字似乎并没有更新。
它仍然是标记-清除吗?它是保守式还是精确式的?它是分代的吗?
Go 1.4+垃圾回收器计划:
在Go 1.1基础上更新的Go 1.3垃圾回收器:
Go 1.1垃圾回收器:
Go 1.0 垃圾回收器:
用不同的 GC 替换 GC 是有争议的,例如:
下一个Go 1.5 并发垃圾收集器需要能够“调节”该gc。
这里提出了一份建议在这篇论文中, 这可能会使其适用于Go 1.5,但也有助于理解Go中的gc。
您可以在1.5之前看到状态(停止世界:STW)
在Go 1.5之前,Go使用了并行停止世界(STW)收集器。
虽然STW收集具有许多缺点,但它至少具有可预测和可控的堆增长行为。
(图片来自GopherCon 2015演讲“Go GC: Solving the Latency Problem in Go 1.5”)
STW(暂停所有线程)垃圾收集器的唯一调优参数是“GOGC”,即在两次垃圾回收之间堆大小相对增长的比例。默认设置为100%,每当堆大小超过上一次回收时的活动堆大小时,就会触发垃圾回收:
STW(Stop The World)收集器中的GC时间。
Go 1.5引入了并发收集器。这比STW收集有很多优点,但由于应用程序可以在垃圾回收器运行时分配内存,因此使堆增长更难控制。
(照片来自GopherCon 2015的演示文稿 "Go GC: Solving the Latency Problem in Go 1.5")
为了达到相同的堆增长限制,运行时必须更早地开始垃圾回收,但是要多早取决于许多变量,其中许多无法预测。
- 如果启动回收器太早,应用程序将执行过多的垃圾回收,浪费CPU资源。
- 如果启动回收器太晚,应用程序将超过所需的最大堆增长。
在不牺牲并发性能的前提下,实现正确的平衡需要仔细控制垃圾回收器。
GC pacing旨在优化两个方面:堆增长和垃圾回收器使用的CPU。
GOMAXPROCS
倍。GOMAXPROCS
为8,则每秒钟墙上的八秒钟会过去,GC每秒钟获得两秒钟的CPU时间。这是GC的实现:
https://github.com/golang/go/blob/master/src/runtime/mgc.go
从源代码中的文档可以看出:
GC与mutator线程并发运行,类型精确(即准确),允许多个GC线程并行运行。它是一个并发的标记和扫描算法,使用写屏障技术。它不是分代式的,也不会压缩内存。分配内存时使用基于P的大小分类分配区域,以最小化内存碎片,同时在常见情况下消除锁定。
我不确定,但我认为当前的GC(tip)已经是并行的,或者至少正在进行中。因此,停止世界属性不再适用于近期或者不会在将来适用。也许其他人可以更详细地澄清这一点。