所以我在go中编写了一个守护程序来处理大约800k文档,并且我遇到了内存不足的问题。
从我从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
}
我不知道它是否在每个循环中重新声明数组或者究竟发生了什么。
非常感谢任何帮助。
答案 0 :(得分:1)
mgo的作者。
您的代码没有任何问题,但它不完整,因此您可能无法显示的内容实际上是泄漏内存。
你能提供泄漏记忆的完整例子吗?
顺便说一句,缓存/池化会话没有意义,因为mgo会在内部为您处理资源池。您必须做的是确保关闭您创建的会话,示例代码会这样做。
OP下面的评论后更新:
似乎问题在于大量的文档。 pastebin.com/jUDmbS4z这将每10-15分钟(大约4-5个循环)崩溃一次。它在一个循环中从mongo获得大约600k文档。
是的,运行同时在内存中加载大量数据的查询很容易因为与mgo无关的多种原因而造成麻烦..内存碎片,非精确收集器等等。只需在项目到达时迭代它们照常;它很舒服,快速,并且会大大减少使用的内存量,正如您已经想到的那样。
答案 1 :(得分:0)
由于调用GetSubscriptions()
然后调用循环result := []Subscription{}
,数组在每个循环中都被定义为inialized,但我认为这不是问题的根源。
问题可能来自您的全局会话,请参阅Database connections in web applications,正确的方法是使用会话池。