фатальная ошибка нехватка памяти

Итак, я написал демон на ходу, который обрабатывает около 800 тысяч документов, и у меня возникла проблема с нехваткой памяти.

Из того, что я видел при получении документов из 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
}

Я не знаю, переопределяет ли он массив с каждым циклом или что именно происходит.

Любая помощь будет принята с благодарностью.


person eastercow    schedule 07.01.2014    source источник
comment
Ваш цикл for является бесконечным циклом и просто собирает результаты из Mongo на каждой итерации.   -  person elithrar    schedule 07.01.2014
comment
Возможно ли, что сеанс кэширует ваши результаты? Вы можете попробовать закрыть/воссоздать свой объект subscribesC при каждом прогоне цикла в качестве теста.   -  person Dmitri Goldring    schedule 07.01.2014
comment
stackoverflow.com/questions/21815635/ следуйте этому, чтобы получить быстрое и быстрое решение.   -  person pankaj kumar    schedule 29.10.2020


Ответы (2)


Массив определенно инициализируется в каждом цикле из-за вызова GetSubscriptions(), а затем внутри цикла result := []Subscription{}, но я думаю, что это не источник проблемы.

Проблема может быть связана с вашим глобальным сеансом, см. раздел подключения к базе данных в Интернете. приложения, правильным способом было бы использование пула сеансов.

Изменить: см. также Как вызвать метод CRUD mongoDB из обработчика?

person ymg    schedule 07.01.2014
comment
Я получаю сообщение об ошибке: pastebin.com/n9b0teSR . Где 139 — это ошибка в GetSubscriptions(), а 166 — это подписки = GetSubscriptions(). - person eastercow; 07.01.2014
comment
Именно err вызвано subscriptionsC, поэтому я подозреваю, что вам следует использовать другой шаблон вместо глобального сеанса. См.: groups.google.com/d/msg/mgo-users/ d62BH1iuzFc/J1cgd5gWjnUJ - person ymg; 07.01.2014
comment
Спасибо чувак. Прежде чем сделать это, я протестировал $where в запросе. Кажется, что если количество возвращаемых записей было меньше, использование памяти было стабильным, а сборка мусора работала правильно. - person eastercow; 07.01.2014
comment
Нет причин использовать пул сеансов в mgo, поскольку ресурсы (например, сокеты) внутренне поддерживаются в пуле. Просто создавайте и закрывайте сеансы по мере необходимости. - person Gustavo Niemeyer; 15.01.2014
comment
@GustavoNiemeyer Я не могу удалить свой ответ, так как ОП уже выбрал его. если он изменился, я удалю его. - person ymg; 16.01.2014

Автор mgo здесь.

В вашем коде все в порядке, но он неполный, поэтому всегда возможно, что что-то, что вы не показываете, на самом деле является утечкой памяти.

Можете ли вы привести полный пример утечки памяти?

Между прочим, нет смысла кэшировать/объединять сеансы, потому что mgo внутренне обрабатывает объединение ресурсов за вас. Что вы должны сделать, так это убедиться, что вы закрываете сеансы, которые вы создаете, что и делает пример кода.

Обновление после комментария ОП ниже:

Кажется, проблема в большом количестве документов. pastebin.com/jUDmbS4z будет падать каждые 10-15 минут (около 4-5 циклов). Он получает около 600 тысяч документов из монго за один цикл.

Да, выполнение запросов, которые загружают в память невероятное количество данных сразу, может легко создать проблемы по ряду причин, не связанных с mgo. Фрагментация памяти, неточный сборщик и т. д. Просто перебирайте элементы по мере их поступления, как обычно; это удобно, быстро и значительно сократит объем используемой памяти, как вы уже поняли.

person Gustavo Niemeyer    schedule 13.01.2014
comment
Дело в том, что я изменил, чтобы не получать все из коллекции, и этот демон теперь работает отлично, с 7 января больше нет утечки памяти и он никогда не перезапускался. Кажется, проблема в большом количестве документов. pastebin.com/jUDmbS4z происходит сбой каждые 10-15 минут (около 4-5 циклов). Он получает около 600 тысяч документов из монго за один цикл. Я думаю, что forEach() вместо заполнения массива исправит это, но также увеличит количество запросов. - person eastercow; 13.01.2014
comment
Ха.. хорошо. Тогда вы используете тонну памяти. Это не утечка в mgo. Обновил ответ. - person Gustavo Niemeyer; 14.01.2014
comment
Никогда не говорил, что это так, я больше думал об ошибке golang, но они сказали, что исправили ее в последней версии. - person eastercow; 15.01.2014