Опрос Python/Django базы данных имеет утечку памяти

У меня есть сценарий Python, выполняющий Django для базы данных и кэш-памяти, но это особенно работает как автономный демон (т.е. не отвечает на запросы веб-сервера). Демон проверяет модель Requisition Django на объекты с a status=STATUS_NEW, тогда отмечает их STATUS_WORKING и помещает их в очередь.

Много процессов (созданное использование пакета мультипроцесса) вытащат вещи из Очереди и действительно работают над Реквизицией с pr.id это было передано Очереди. Я полагаю, что утечка памяти находится, вероятно, в следующем коде (но это могло быть в коде 'Рабочего' с другой стороны Очереди, хотя это маловероятно потому что, потому что емкость памяти растет, даже когда никакие Реквизиции не подходят - т.е. когда рабочие все блокируются на Queue.get ()).

from requisitions.models import Requisition # our Django model
from multiprocessing import Queue

while True:
    # Wait for "N"ew requisitions, then pop them into the queue.
    for pr in Requisition.objects.all().filter(status=Requisition.STATUS_NEW):
        pr.set_status(pr.STATUS_WORKING)
        pr.save()
        queue.put(pr.id)

    time.sleep(settings.DAEMON_POLL_WAIT)

Где settings.DAEMON_POLL_WAIT=0.01.

Кажется, оставляю ли я это выполнение сроком на время (т.е. пара дней), процесс Python вырастет до бесконечного размера, и в конечном счете система исчерпает память.

Что продолжается здесь (или как я могу узнать), и что еще более важно - как можно выполнить демона, который делает это?

Моя первая мысль состоит в том, чтобы изменить динамическую из функции, особенно путем помещения проверки на новые объекты Реквизиции в a django.core.cache cache, т.е.

from django.core.cache import cache

while True:
    time.sleep(settings.DAEMON_POLL_WAIT)
    if cache.get('new_requisitions'):
       # Possible race condition
       cache.clear()
       process_new_requisitions(queue)

 def process_new_requisitions(queue):
    for pr in Requisition.objects.all().filter(status=Requisition.STATUS_NEW):
        pr.set_status(pr.STATUS_WORKING)
        pr.save()
        queue.put(pr.id)

Процесс это создает Реквизиции с status=STATUS_NEW может сделать a cache.set('new_requisitions', 1) (или альтернативно мы могли поймать сигнал или событие Requisition.save(), где новая Реквизиция создается и затем установила флаг в кэше оттуда).

Однако я не уверен, что решение, которое я предложил здесь, обращается к проблемам памяти (которые, вероятно, связаны со сборкой "мусора" - так обзор посредством process_new_requisitions может решить проблему).

Я благодарен за любые мысли и обратную связь.

15
задан Brian M. Hunt 25 February 2010 в 22:20
поделиться

2 ответа

Вам необходимо регулярно сбрасывать список запросов, которые Django сохраняет для целей отладки. Обычно он очищается после каждого запроса, но поскольку ваше приложение не основано на запросах, вам нужно сделать это вручную:

from django import db

db.reset_queries()

См. Также:

  • «Отладка утечки памяти Django с помощью TrackRefs и Guppy» by Mikko {{ 1}} Охтамаа:

    Django отслеживает все запросы для целей отладки (connection.queries). Этот список сбрасывается в конце HTTP-запроса. Но в автономном режиме запросов нет. Поэтому вам нужно вручную возвращаться к списку запросов после каждого рабочего цикла

  • "Почему Django утекает память?" в Django FAQ - здесь говорится как о настройке DEBUG ] на False , что всегда важно, так и о об очистке списка запросов используя db.reset_queries () , важно в таких приложениях, как ваше.

38
ответ дан 1 December 2019 в 00:33
поделиться

Имеется ли в файле settings.py для процесса демона DEBUG = True ? Если это так, Django хранит в памяти записи обо всех SQL, которые он выполнял на данный момент, что может привести к утечке памяти.

5
ответ дан 1 December 2019 в 00:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: