En primer lugar, DEBUG = False
en settings.py, entonces no, connections['default'].queries
no está creciendo y creciendo hasta que consume toda la memoria.¿Por qué la memoria no se libera al sistema después de grandes consultas (o series de consultas) en django?
Comencemos con el hecho de que he cargado la tabla User
de django.contrib.auth.models.User
con 10000 usuarios (cada uno llamado 'test #' donde # es un número entre 1 y 10000).
Aquí está la vista:
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('')
He adjuntado la vista por encima de la /leak/
url e iniciar el servidor de desarrollo (con DEBUG = False, y he probado y no tiene nada a hacer con ejecutar un servidor de desarrollo frente a otras instancias).
después de correr:
% curl http://localhost:8000/leak/
El proceso de la memoria de ejecución del servidor crece a alrededor del tamaño visto desde ps aux
de salida por debajo y luego se mantiene en ese nivel.
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
A continuación, ejecutar el comando anterior curl
anterior no parecen crecer el uso de memoria de la instancia (que yo esperaba de una verdadera pérdida de memoria?), Debe ser re-uso de la memoria? Sin embargo, creo que hay algo mal aquí que la memoria no se libera en el sistema (sin embargo, entiendo que puede ser un mejor rendimiento que Python NO libere la memoria).
Después de esto, ingenuamente intenté ver si python liberaría grandes trozos de memoria que asignó. Así que intento lo siguiente de una sesión de pitón:
>>> a = ''
>>> a += 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' * 10000000
>>> del a
La memoria se asigna en la línea a += ...
como se esperaba, pero cuando del a
sucede, se libera la memoria. ¿Por qué el comportamiento es diferente para los conjuntos de consulta django? ¿Es algo que django tiene la intención de hacer? ¿Hay alguna forma de cambiar este comportamiento?
Literalmente he pasado 2 días depurando este comportamiento sin saber a dónde ir ahora (aprendí a usar guppy Y objgraph que parecen no señalar nada interesante que pueda entender).
ACTUALIZACIÓN: Esta podría ser la gestión de memoria, simplemente pitón en el trabajo y no tienen nada que ver con Django (django sugerido en la lista de distribución), pero me gustaría la confirmación de alguna manera replicar esto en pitón exterior de Django.
ACTUALIZACIÓN: Al usar la versión Python 2.6.5
+1. Muy interesado en las respuestas de esta pregunta. También reconocí pérdidas de memoria extrañas con Django durante algún tiempo en la producción (DEBUG = False también e incluso con aplicaciones/proyectos muy simples). –
¿Qué sucede si "del usuario"? –
¿Qué versión de Python está usando (tanto para el servidor como para la prueba de línea de comando)? Las versiones anteriores no liberan la memoria asignada para los objetos al sistema, por lo que si su versión local es 2.5 o posterior, pero su servidor está ejecutando 2.4, ese puede ser su problema. Las grandes asignaciones individuales (como su secuencia grande) también pueden omitir el asignador: en su lugar, vea lo que sucede con algo como '([[]] * 10 ** 6)'. – ncoghlan