Wired 上这篇关于 Dropbox 的 MagicPocket 产品从 Go 转向 Rust 的文章说
\n\n\n\n\n\xe2\x80\x9c内存占用\xe2\x80\x9d\xe2\x80\x94运行 Magic Pocket\xe2\x80\x94 时所需的计算机内存量对于公司试图构建的海量存储系统来说太高了。
\n
问题:Go 的“内存占用”到底是什么(它从哪里来,如何测量等,它与垃圾收集、二进制大小有关,它是否总是很高)以及为什么它比 Rust 更高吗?
\n“它的内存占用很大”只是他们的程序使用大量 RAM 的另一种说法。它与垃圾收集有关,因为 GC 程序仅定期释放内存(因为每个 GC 周期都会占用 CPU 时间),而手动内存管理往往会在内存未使用时或多或少地释放内存。
手动内存管理的缺点是,错误可能会导致崩溃和安全错误(如在 C++ 中,在内存被重用于其他用途后,您可能会意外使用已释放的变量),或者您必须努力表达确切的生命周期代码中每个变量、引用等的信息,以便编译器可以检查它们是否以有效的方式使用(如在 Rust 中,您与借用检查器交互以根除代码中潜在的不正确的内存使用) )。
《连线》故事中的这句话听起来像是“内存足迹”是一个可以分配给任何语言的简单可测量量(并且您的问题将这个想法推向了逻辑结论)。事情没那么简单。在不同的语言中,做不同的事情在内存、性能等方面有不同的成本,你必须了解语言/运行时的细节才能知道该语言如何与给定类型的程序一起工作。
例如,CPython 具有引用计数,可以更快地释放未使用的内存,但代价是必须存储和更新引用计数。一方面,Java 具有诸如对象头之类的东西,它们为每个对象增加了一定量的内存开销,但使用了一些 Go 还没有的技巧来加速垃圾收集(如分代收集)。或者在 Go 中,您可能会尝试通过使用空闲池回收内存并调整 GOGC 以更频繁地释放未使用的内存来减少程序的内存占用,正如 kostya 所说。
更重要的一点并不是我列出的那些具体细节非常重要,而是除了“更高的内存占用量”或“更低的内存占用量”之外,还有很多细节需要考虑。
因此:“内存占用”是指具有特定工作负载的特定程序占用的 RAM 量。从更大的角度来看,这是像您、我或 Dropbox 团队这样的人必须进行的一系列权衡中的一个因素。