Go(lang)内存使用情况:RSIZE增长和VSIZE为139GB?

Dan*_*e B 5 memory-leaks memory-management go

我正在Go中编写我的第一个webserver/webservices程序,我意识到在向webservices重复相同的请求之后,RSIZE(如命令行程序"top"所示)会增长.这是否意味着内存泄漏?

我还注意到我的应用程序和"top"上的go进程都有一个139GB的VSIZE(两者都是那个大小).这是正常的吗?

我在OS X 10.8上使用Go 1.1.2

非常感谢

two*_*two 4

大 VSIZE 并不意味着您真正使用了物理内存;而是意味着您正在使用物理内存。不会担心这个。

RSIZE 在单个请求后增长也不用担心。RAM 通过垃圾收集来回收,这会消耗 CPU 周期,因此 Go 和其他 GC 语言会等待许多请求,直到它们需要释放 RAM(或者至少直到分配了大量 RAM)来运行收集。更少的集合 => 花费的 CPU 时间更少。

通常意义上的泄漏很少见,因为 GC 最终应该释放您没有引用的内存。如果您的缓冲区根据需要增长但从不缩小,那么它们可能会产生类似泄漏的效果,并且如果您不小心持有对确实已死的内存的引用,则可能会遇到问题。但除非这个过程永远持续增长,否则我不会认为你会遇到这个问题。

以下是 Go 的一些内存管理技巧;有些也间接适用于其他语言:

  • 很多时候你不需要担心。收集通常非常快,并且相对于数据大小,您通常有大量 RAM 可供使用。在开始之前,请确保有一个问题需要解决。:)
  • runtime.ReadMemStats(ms)可以告诉您程序在 GC 中花费了多长时间,以及许多其他有用的信息,例如您分配了多少(请参阅http://golang.org/pkg/runtime/runtime上的模块文档)
  • 如果您在 GC 上花费了太多时间并且不知道原因,那么下一步就是 memprofile;Go 博客上有一个完整的示例,涉及为程序提供可选的 -memprofile 标志:http://blog.golang.org/profiling-go-programs
  • 一般来说,您可以通过减少不必要的分配来减少 GC,尤其是大对象的分配(例如保存整个 HTTP 响应的缓冲区)。
    • 有时,有一些自然的方法可以在不使程序复杂化的情况下做到这一点——Writer例如,您可以将输出流式传输到 a 而不是缓冲一个大响应,或者在循环的多次迭代中重用一个对象而不是每次都进行分配。
    • 其他时候,您可以回收大型/经常分配的对象,而不是创建新对象;标准sync.Pool包对此有所帮助,并且CloudFlare 博客上sync.Pool有一个关于回收的很好的一般描述(以前是标准的)。