Cómo cazar una fuga de memoria en .Net (y II)

Comentaba hace unos días como he sufrido una fuga de memoria en .Net, esas que en teoria son ‘imposibles’ y presentaba un caso mínimo que lo reproducía. Luego, explique como dilucidar si se trataba de una fuga de memoria manejada o de memoria nativa. Hoy toca hablar de cómo llegue a determinar en que lugar exacto del código se estaba produciendo la fuga de memoria en cuestión.

La herramienta que utlice para ello fue el CLR Profiler, que nos permite monitorizar todas las asignaciones de memoria que realiza una aplicación manejada. Para ello basta con ejecutar la aplicación bajo la supervisión del CLR Profiler. Podeís descargar esta poderosa herramienta de manera totalmente gratuita. Para instalar la aplicación solo es necesario ejecutar el archivo autodescomprimible.

Para ejecutar una aplicación bajo el profiler basta con pulsar sobre el botón Start Application… y seleccionar el ejecutable de nuestra aplicación. Si se trata de un servicio o una aplicación Asp.net tenemos que usar el menu File y elegir Profile Service… o Profile ASP.NET. Es importante ejecutar el profiler con permisos de administrador, sino no será capaz de adjuntarse a la aplicación y recoger datos sobre las asignaciones de memoria realizadas por la aplicación.

image

Una vez ejecutada nuestra aplicación bajo el profiler podemos usar el botón Show Heap now, que aparecerá habilitado, para ver el estado de la memoria de la memoria de nuestro proceso. Esto nos permite obtener una imagen de la memoria en un instante determinado y también comparar los objetos que tenemos en memoria en dos instantes determinados. El profiler nos da numerosas representaciones de las asignaciones de memoria, en concreto me voy a fijar ahora en la representación en forma de histograma. Esta representación nos da una idea visual de que objetos son los más numerosos de los que nuestra aplicación crea, evidentemente si tenemos una fuga de memoria relacionada con memoria manejada tendremos un gran numero de objetos de los que son responsables de la fuga. Aplicando el profiler al caso mínimo que publique en mi primer post y mostrando la vista de histograma (menu contextual Show Histogram) vemos como System.WeakReference es el objeto más numeroso de los creados por nuestra aplicación.

image

Ahora nos queda saber quien esta creando ese objeto. Para ello, con el menu contextual  de la barra del histograma Show who allocated nos permite ver en forma de arbol que funciones son las que han creado esos objetos. Vemos que aquí ya aparecen funciones de nuestro código, lo que sin duda nos llevará a tras inspeccionar el código plantear una hipótesis fundamentada sobre por qué se esta producciendo la fuga.

image

Una vez terminada la ejecución de la aplicación, podemos obtener un motón de información sobre como se comportó la aplicación en lo relativo a la memoria.

image

A la hora de cazar fugas de memoria es especialmente útil la vista de línea de tiempos (botón Time Line)

image

Esta vista nos muestra como nuestra aplicación asigna memoria y la libera (se presenta una típica figura de dientes de sierra) y como hay una porción creciente de memoria que nunca se libera (area roja). Pinchando en ese area, podemos ver que se corresponde con objetos WeakReference. Una vez más podemos usar el menu contextual Show Who Allocated para saber que funciones son las reponsables de la cración de dichos objetos.

Otra información relevante que nos da este gráfico es la cantidad de memoria que tenemos en colecciones de segunda generación (area amarilla) o lo que es lo mismo el volumen de objetos que está sobreviviendo de manera persistente al recolector de factura, comportamiento sintomático de un problema de fuga de memoria. En este caso vemos como el volumen de las colecciones de segunda generación cada vez crece mas y como es debido precisamente a objetos de tipo WeakReference. Igual que antes podemos usar el menu contextual Show Who Allocated para obtener información de que funciones son las responsables de la creación de dichos objetos.

El CLR Profiler es una poderosa herramienta a la hora de diagnosticar problemas de memoria de nuestra aplicación, sean estos fugas de memoria o un consumo demasiado alto de la misma.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *