Уведомления

Группа в Telegram: присоединиться

#1 Сен. 11, 2019 12:22:23

VadimK
Зарегистрирован: 2013-07-03
Сообщения: 127
Репутация: +  7  -
Профиль   Отправить e-mail  

memory leak в простом скрипте, но с большим объемом данных.

Есть скрипт с Django на простой логике:

 def task(order_id):
    order = Orders.objects.get(pk=order_id)
    cache, created = OrderIndexer.objects.get_or_create(order=order_id)
    cache.name = order.country_from_name
    # и так далее
    cache.save()
    
    del order
    del cache
    
rs = Orders.objects.filter()
for row in rs:
    task(row.id)
    del row

Грубо говоря вытягиваем из одной таблицы данные, агрегируем их в нужный вид и записываем в другую. Записей много. За время работы скрипт съедает более 1 гига оперативки. Попытки принудительно удалять объекты ничего не дают. Видно как постепенно размер потребляемой памяти растет, а по окончанию освобождается.

Скрипт вызывается из консоли, т.е. поведение прекрасно видно.

Офлайн

#2 Сен. 11, 2019 13:14:07

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 7086
Репутация: +  477  -
Профиль   Отправить e-mail  

memory leak в простом скрипте, но с большим объемом данных.

VadimK
первым делом попробуйте принудительно коммитить транзакцию
во-вторых, если вы экономите пямять, то зачем делаете select *? Используйте only и defer, например,

 order = Orders.objects.filter(pk=order_id).only("name")[0]
в-третьих, старайтесь комбинировать запросы, типа
 cache = OrderIndexer.objects.filter(order__in=Orders.objects.filter(pk=order_id).only("id"))
это уменьшит количество запросов, и создаваемых объектов.

VadimK
Попытки принудительно удалять объекты ничего не дают.
вы их не удаляете принудительно, вы их помечаете для удаления для сборщика мусора, сам сборщик никуда не девается. Попробуйте его отключить

ну и гонять гигабайты данных по сети, только чтобы использовать всю “мощь” идиотского джанговского ОРМ - ну так себе идея. Вы же понимаете, что скопировать миллион значений из одной таблицы в другую можно миллионом запросов, а можно одним? Вы выбрали путь миллиона запросов, и удивляетесь, что отъело целый гигабайт. Сделайте один запрос на чистом SQL и у вас отъест 0 байт.



Онлайн

#3 Сен. 11, 2019 14:34:44

VadimK
Зарегистрирован: 2013-07-03
Сообщения: 127
Репутация: +  7  -
Профиль   Отправить e-mail  

memory leak в простом скрипте, но с большим объемом данных.

Это не весь скрипт, там десятки полей включая текстовые. Данные агрегируются для поиска, формируются json объекты для последующего использования и т.п. Это ни каким одним запросом не сделать.


Если правильно понимаю, внутри task() формируются объекты cache, order - далее помечаются как удаленные и отправляются в память. Следующим вызовом формируются новые, снова помечаются и так далее по циклу.

gc.collect() в цикле в общем то решило проблему, рост минимальный

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version