2011-06-30 16 views
5
import json 
import time 
from itertools import count 

def keygen(size): 
    for i in count(1): 
     s = str(i) 
     yield '0' * (size - len(s)) + str(s) 

def jsontest(num): 
    keys = keygen(20) 
    kvjson = json.dumps(dict((keys.next(), '0' * 200) for i in range(num))) 
    kvpairs = json.loads(kvjson) 
    del kvpairs # Not required. Just to check if it makes any difference        
    print 'load completed' 

jsontest(500000) 

while 1: 
    time.sleep(1) 

Linux superior indica que el proceso de pitón mantiene ~ 450Mb de RAM después de la finalización de la función 'jsontest'. Si se omite la llamada a 'json.loads', entonces este problema no se observa. A gc.collect después de esta ejecución de la función libera la memoria.Python memoria JSON inflar

Parece que la memoria no se guarda en ningún caché ni en el asignador de memoria interna de python, ya que la llamada explícita a gc.collect libera la memoria.

¿Esto está sucediendo porque nunca se alcanzó el umbral para la recolección de basura (700, 10, 10)?

Puse un código después de jsontest para simular el umbral. Pero no ayudó.

Respuesta

2

poner esto en la parte superior de su programa

import gc 
gc.set_debug(gc.DEBUG_STATS) 

y obtendrá la salida impresa cada vez que hay una colección. Verá que en su código de ejemplo no hay recolección después de que se complete jsontest, hasta que el programa finalice.

Usted puede poner

print gc.get_count() 

para ver los recuentos actuales. El primer número es el exceso de asignaciones sobre desasignaciones desde la última colección de la generación 0; el segundo (tercero respectivamente) es el número de veces que se ha recolectado la generación 0 (resp 1) desde la última colección de la generación 1 (resp 2). Si imprime estos inmediatamente después de que se complete jsontest, verá que los recuentos son (548, 6, 0) o algo similar (sin duda esto varía según la versión de Python). Por lo tanto, no se alcanzó el umbral y no se realizó ninguna recolección.

Este es el comportamiento típico de la programación de recolección de basura basada en umbrales. Si necesita que la memoria libre se devuelva al sistema operativo de manera oportuna, debe combinar la programación basada en umbrales con la programación basada en el tiempo (es decir, solicitar otra recopilación después de que haya transcurrido un cierto tiempo desde la última recopilación , incluso si no se ha alcanzado el umbral).

+0

Incluso si llamamos a jsontest varias veces, la memoria permanece en ~ 450MB. ¿Es esta la memoria utilizada por la última llamada jsontest? Este código es parte de una aplicación web que procesa mensajes json. Incluso después de ejecutar la aplicación web durante una hora, la memoria no parece liberarse. ¿Hay alguna solución para esto que no sea gc.collect? – Anoop

+1

Intenta imprimir 'gc.get_count()' después de cada llamada a 'jsontest' y todo debe ser claro. Además, ¿qué hay de malo en llamar a 'gc.collect'? –