1

所以我在 go 中编写了一个守护进程来处理大约 80 万个文档,但我遇到了内存不足的问题。

从我从 mongodb 获取文档时看到的情况来看,每次循环都会增加内存使用量。

func main() {
session, err := mgo.Dial("localhost")
if err != nil { panic(err) }
defer session.Close()

subscriptionsC  = session.DB("sm").C("subscriptions")
subscriptions   := []Subscription{}

for {
    subscriptions = GetSubscriptions()

另一个功能是:

func GetSubscriptions()([]Subscription) {
    result  := []Subscription{}
    err    := subscriptionsC.Find(nil).Prefetch(0.0).All(&result)

    if err != nil { Log("signups_err", err.Error() + "\n") }
    return result
}

我不知道它是否在每个循环中重新声明数组或究竟发生了什么。

任何帮助将不胜感激。

4

2 回答 2

1

mgo的作者在这里。

您的代码没有任何问题,但它不完整,因此您未显示的内容总是有可能实际上是内存泄漏。

您能否提供一个泄漏内存的完整示例?

顺便说一句,缓存/池会话没有意义,因为 mgo 在内部为您处理资源池。您必须做的是确保关闭您创建的会话,示例代码就是这样做的。

OP在下面的评论后更新:

似乎问题出在大量文档上。pastebin.com/jUDmbS4z 这将每 10-15 分钟(大约 4-5 个循环)崩溃一次。它在一个循环中从 mongo 获得了大约 600k 文档。

是的,运行一次在内存中加载大量数据的查询很容易因为与 mgo 无关的多种原因而造成麻烦。内存碎片、非精确收集器等。只需像往常一样在项目到达时对其进行迭代;正如您已经想到的那样,它舒适,快速,并且会大大减少使用的内存量。

于 2014-01-13T14:15:27.240 回答
0

由于调用GetSubscriptions()然后在循环内部,数组肯定在每个循环中被初始化result := []Subscription{},但我认为这不是问题的根源。

问题可能来自您的全局会话,请参阅Web 应用程序中的数据库连接,正确的方法是使用会话池。

编辑:另请参阅如何从处理程序调用 mongoDB CRUD 方法?

于 2014-01-07T13:52:28.787 回答