2014-01-07 95 views
1

所以我編寫了一個守護進程,用於處理大約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

您的for循環是一個無限循環,只是在每次迭代中收集來自Mongo的結果。 – elithrar

+0

會話緩存結果有可能嗎?作爲測試,您可以嘗試通過循環在每次運行時關閉/重新創建您的subscriptionsC對象。 –

回答

0

由於呼叫GetSubscriptions(),然後在循環result := []Subscription{}內,該陣列在每個循環中都被明確地初始化,但我認爲這不是問題的根源。

問題可能來自您的全局會話,請參閱Database connections in web applications,正確的方法是使用會話池。

編輯:又見How do I call mongoDB CRUD method from handler?

+0

我得到的錯誤是:http://pastebin.com/n9b0teSR。其中139是GetSubscriptions()中的「err」,166是訂閱= GetSubscriptions() – eastercow

+0

確切地說'err'是由'subscriptionsC'引起的,這就是爲什麼我懷疑你應該使用另一種模式而不是全局會話。請參閱:https://groups.google.com/d/msg/mgo-users/d62BH1iuzFc/J1cgd5gWjnUJ – ymg

+0

謝謝。在做這件事之前,我用一個$在查詢中進行了測試。似乎如果返回的記錄數量較少,則內存使用情況穩定並且垃圾收集工作正常。 – eastercow

1

作者氧化鎂這裏。

你的代碼沒有問題,但它不完整,所以總是有可能你沒有顯示的東西實際上是在泄漏內存。

你能提供一個泄漏內存的完整例子嗎?

順便說一下,緩存/池會話沒有意義,因爲mgo在內部爲您處理資源池。你必須做的是確保你關閉你創建的會話,這個示例代碼就是這樣做的。下面OP的評論後

更新:

看來這個問題是有大量的文檔中。 pastebin.com/jUDmbS4z這會每10-15分鐘一次(約4-5次循環)。它在一個循環中從mongo獲得大約60萬個文檔。

是的,運行在一次加載在存儲器中的數據的量荒謬的查詢可以很容易地爲多種原因無關的MgO ..存儲器碎片,非精確集電極等製造麻煩只是迭代項因爲他們照常到達;它是舒適,快速的,並且會大大減少使用的內存量,正如您已經想到的那樣。

+0

事情是我改變了沒有從集合中得到所有東西,而且這個守護進程現在工作得很完美,自從7日開始沒有更多的內存泄漏,並且從未重新啓動。似乎問題在於大量的文檔。 http://pastebin.com/jUDmbS4z這將每10-15分鐘一次(大約4-5次循環)。它在一個循環中從mongo獲得大約60萬個文檔。我認爲forEach()而不是填充數組可以解決它,但也會增加查詢的數量。 – eastercow

+0

哈..好吧。然後,你會使用大量的記憶。這不是mgo中的泄漏。更新了回覆。 –

+0

從來沒有說過,我在考慮更多的golang bug,但他們說他們用最新版本修復了它。 – eastercow