Tenía una aplicación que requería cargar algunas imágenes y realizar operaciones en ellas. Dependiendo del tamaño de las imágenes, los requisitos de memoria de la aplicación podrían hacer que todo el sistema se bloquee. Esto necesitaba ser detenido … o al menos entendido.

Mirando alrededor, encontré varias herramientas para diagnosticar mi problema y probé 2.

Pympler

Pympler es una herramienta para analizar el uso de memoria de su aplicación. La mayor parte es un envoltorio sobre otras aplicaciones especializadas en algún diagnóstico específico.

Utilicé dos de las herramientas que proporcionaba: asized y tracker.

asized mide la memoria utilizada por el objeto pasado. Tiene varias opciones que puede inspeccionar en la documentación para ajustar la forma en que desea que mida, pero para mí los valores predeterminados funcionaron.

Lo usas así:

print(asizeof.asized(obj, detail=10).format())

Esto le da el tamaño en bytes de ese objeto, para que pueda saber si algo que debería haberse liberado todavía está en uso. En mi caso, tenía una referencia a una imagen dentro de uno de mis objetos, y no me di cuenta hasta que verifiqué el tamaño de mi objeto en un par de lugares donde debería estar casi vacío.

La otra herramienta es el tracker. Este funciona un poco diferente. Lo inicias en algún punto de tu aplicación y le pides que te dé una diferencia en otro. Imprime un informe de los objetos creados durante ese lapso y su tamaño.

Lo usas así (tomado de la documentación):

tr = tracker.SummaryTracker()
function_without_side_effects()
tr.print_diff()

Es bastante fácil de configurar y puede saber qué objetos permanecen en la memoria para un fragmento de código determinado.

LEER
Testeando archivos con Python/Django

Memory-profiler

Memory-profiler, a diferencia de pympler, tiene algunas dependencias. Tuve que instalar tk y matplotlib en mi sistema, junto con psutil. Sin embargo, esta herramienta puede proporcionarle el consumo de memoria de su aplicación por línea o contra el tiempo. Esto me ayudó a encontrar dónde estaban mis picos de rendimiento. Al principio tenía algo como esto:

Horrible, ¿verdad? Tenía una función para mostrar una imagen en un widget, pero cada vez que actualizaba la imagen para mostrar, mantenía una referencia a la anterior. Es fácil correlacionar esa situación con el gráfico. Simplemente seguía desperdiciando memoria.

Una vez que sabe cuál es el problema, es más fácil de resolver (la mayoría de las veces). Lo arreglé y ahora mi memoria se comporta así:

Básicamente, el widget dejó de desperdiciar mi memoria, con el máximo ahora siendo menos de la mitad en el análisis anterior. Los “picos” están correlacionados con la forma en que estoy cargando la imagen en la aplicación. Tengo que crear una copia, cambiar su formato y pasarla al widget, pero una vez hecho eso, se libera esa memoria. Mi aplicación ya no depende de la cantidad de imágenes.

Al final, la mayor parte de la optimización se redujo a agregar una línea de código para borrar referencias antiguas, pero las herramientas para diagnosticar el problema fueron vitales para comprender mi problema y obtener una visión clara del rendimiento y el comportamiento de mi aplicación.


Comentarios