punteros - Encuentra todas las referencias a un objeto en python
python memoria (2)
¿Cuál es una buena manera de encontrar todas las referencias a un objeto en python?
La razón por la que pregunto es que parece que tenemos una "pérdida de memoria". Estamos cargando archivos de imágenes al servidor desde un navegador web. Cada vez que hacemos esto, el uso de memoria en el servidor aumenta proporcionalmente al tamaño del archivo que se acaba de cargar. La recolección de elementos no utilizados de python nunca libera esta memoria, por lo que creo que probablemente haya referencias extraviadas que apuntan a los datos de la imagen que no se eliminan o están fuera del alcance, incluso al final de cada solicitud.
Me imagino que sería bueno poder preguntar a Python: "¿Qué referencias apuntan a esta memoria?" de modo que pueda averiguar qué es lo que impide que la recolección de basura la libere.
Actualmente estamos ejecutando Python y Django en un servidor Heroku.
Cualquier sugerencia e ideas son apreciadas, muchas gracias!
El módulo gc
de Python tiene varias funciones útiles, pero suena como gc.get_referrers()
es lo que estás buscando. Aquí hay un ejemplo:
import gc
def foo():
a = [2, 4, 6]
b = [1, 4, 7]
l = [a, b]
d = dict(a=a)
return l, d
l, d = foo()
r1 = gc.get_referrers(l[0])
r2 = gc.get_referrers(l[1])
print r1
print r2
Cuando ejecuto eso, veo el siguiente resultado:
[[[2, 4, 6], [1, 4, 7]], {''a'': [2, 4, 6]}]
[[[2, 4, 6], [1, 4, 7]]]
Puedes ver que la primera línea es l
y d
, y la segunda línea es solo l
.
En mis breves experimentos, he encontrado que los resultados no siempre son tan limpios. Las cadenas y tuplas internas, por ejemplo, tienen más referencias de las que cabría esperar.
La biblioteca estándar de Python tiene un módulo gc
que contiene la API del recolector de basura. Una de las funciones que posiblemente quieras tener es
gc.get_objects()
Esta función devuelve la lista de todos los objetos actualmente rastreados por el recolector de basura. El siguiente paso es analizarlo.
Si conoce el objeto que desea rastrear, puede usar la función getrefcount
del módulo sys
:
>>> x = object()
>>> sys.getrefcount(x)
2
>>> y = x
>>> sys.getrefcount(x)
3