6

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

我还注意到,我的应用程序和“top”上的 go 进程都有 139GB 的 VSIZE(它们都是那个大小)。正常吗?

我在 OS X 10.8 上使用 Go 1.1.2

非常感谢

4

1 回答 1

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 响应的缓冲区)。
    • 有时有一些自然的方法可以做到这一点而不会使程序复杂化——例如,您可以将输出流式传输到 aWriter而不是缓冲大响应,或者在循环的多次迭代中重用对象而不是每次都分配。
    • 其他时候,您可以回收大型/经常分配的对象,而不是创建新对象;标准包对此有所帮助,CloudFlare 博客上sync.Pool有一个很好的关于回收的一般描述(以前sync.Pool是标准的)。
于 2013-11-03T06:01:11.413 回答