为什么Go语言垃圾回收机制不好? - Reddit


有两个主要的批评阵营:

  1. Rust/C++的人就是不相信GC;他们认为GC太浪费了,尽管他们99%的软件会对free()内存进行O(n)次调用,而不是一次大的free()调用--关键是他们*可以*控制他们的内存取消分配,如果他们想*的话。
  2. Java的人认为,你应该能够超快地分配成吨的垃圾,即使这意味着产生漫长的垃圾收集暂停时间(虽然他们会说有支持低延迟的GC,但似乎几乎没有人使用它们,大概是因为有隐藏的权衡)。Idiomatic Go只是没有像Java那样分配大量的垃圾,它的GC暂停时间更短,GC的复杂性也因此大大降低(但分配的时间更长)。

还有一些微小的第三阵营在特定情况下存在与巨大堆相关的病态问题。我不确定这些病态问题是否已在后续的 Go 版本中得到修复

只不过,目前的JVM使用的是先进的GC,支持这个。因此,为了补充你的批评者阵营。

Gophers认为:Java(和C#)是缓慢和臃肿的,它的GC让世界停止了巨大的停顿,因为开发者产生了大量的垃圾,而GC无法跟上。

但,这并不是真的:
最新一代的Java GC是非常好的,比Go GC要先进得多。Go的GC很古老,而且肯定有严重的缺陷。我们不得不花大量的时间来解决这些问题,以免我们的应用程序处于近乎持续的goroutine GC辅助模式下。

实际上,以上这些极端的观点都不完全正确。有时候,没有一个GC是正确的,很多时候Go就足够了,很多时候Java也够了。
这是关于理解用例,为工作选择正确的工具,然后在理解这些工具的特点和限制的情况下编写软件。

一旦您开始将应用程序延迟等归咎于 GC 引擎。是时候进行重组了。

不过,有一个完美解决办法:

  • Go 有一个设置可以完全禁用 GC。(通过将GOGC环境变量设置为off)
  • 您在配备 1TB RAM 的服务器上安装您的服务,然后使用 Crontabs 不时地重新启动该服务!!
  • 如果重新启动服务还不够......您可以扩展 crontab 并偶尔重新启动整个操作系统。

即使 C++ 和 Go 总体上具有相同的性能,但 3% 的时间 Go 只是在 GC 运行时完全暂停。无论如何,Go 对于 Web 应用程序来说都很好,因为每隔一段时间你的端点响应时间就会稍微慢一些。但对于视频游戏来说,每秒 30 毫秒内您无法绘制图形,这会导致游戏玩法卡顿。
所以对于一致性至关重要的应用程序,您必须围绕 GC 做出一些谨慎的决定。但总体性能通常非常接近,除非是在异常紧张的应用程序中。

GC最终变成了一个愚蠢的“拾垃圾者”,偶尔决定在马路中间捡垃圾,就在救护车来的时候,他不明白 "我需要让开,这比我捡垃圾重要得多"。同样,这个 "捡垃圾的人 "也倾向于在路上没有什么有趣的事情发生时就坐在那里,他可以捡垃圾,但 "没有那么多垃圾,何必呢"。后者的决定偶尔会导致 "路上有辆救护车过来了,嘿嘿,连我都知道我需要避开,但好在有太多的垃圾,除非我把这些垃圾清理干净,否则它永远也到不了!"
它适用于很多事情,确实如此。它只是不适合于那些你不能偶尔让人等待的事情,或者在某一时刻为进程保持尽可能少的内存足迹是很重要的。