Прежде всего, DEBUG = False
в settings.py, поэтому no, connections['default'].queries
не растет и не растет, пока не использует всю память.
Давайте начнем с того, что я загрузил таблицу User
из django.contrib.auth.models.User
с 10000 пользователями (каждый из них назвал 'test #', где # - число от 1 до 10000).
Вот представление:
from django.contrib.auth.models import User
from django.http import HttpResponse
import time
def leak(request):
print "loading users"
users = []
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
users += list(User.objects.all())
print "sleeping"
time.sleep(10)
return HttpResponse('')
Я привязал представление выше к URL-адресу /leak/
и запустил сервер разработки (с DEBUG = False, и я протестировал его, и он не имеет никакого отношения к запуску сервера разработки против других экземпляров).
После запуска:
% curl http://localhost:8000/leak/
Память процесса сервера-хранилища растет примерно до размера, видимого из ps aux
вывода ниже, а затем остается на этом уровне.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
dlamotte 25694 11.5 34.8 861384 705668 pts/3 Sl+ 19:11 2:52 /home/dlamotte/tmp/django-mem-leak/env/bin/python ./manage.py runserver
Тогда выполнение вышеприведенной команды curl
, похоже, не увеличивает использование памяти экземпляра (что я ожидал от истинной утечки памяти?), он должен повторно использовать память? Тем не менее, я чувствую, что здесь что-то не так, что память не получает доступ к системе (однако я понимаю, что это может быть лучшая производительность, что python НЕ выпускает память).
После этого я наивно пытался увидеть, выпустит ли python большие куски памяти, которые он выделил. Поэтому я пытаюсь выполнить следующее из сеанса python:
>>> a = ''
>>> a += 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' * 10000000
>>> del a
Память выделяется в строке a += ...
, как ожидалось, но когда del a
происходит, память освобождается. Почему поведение django отличается от поведения? Это что-то, что джанго намеревается сделать? Есть ли способ изменить это поведение?
Я буквально провел 2 дня, отлаживая это поведение, не представляя, куда идти дальше (я научился использовать guppy AND objgraph, который, похоже, не указывает на что-либо интересное, что я могу понять).
ОБНОВЛЕНИЕ: Это может быть просто управление памятью python на работе и не имеет ничего общего с Django (предлагается в списке рассылки django-users), но я бы хотел подтвердить, как-то реплицируя это в python вне Django.
ОБНОВЛЕНИЕ: Использование python версии 2.6.5