Detectando problemas de memoria con Silverlight

Hola a todos!

Hoy vamos a hablar sobre un memory leak encontrado en Silverlight 4 y reportado en el foro de silverilght.net por el usuario tsheflin. Como sabrás Silverlight está basado en tecnología .net lo que significa que puedes escribir tus aplicaciones en C# o en Visual Basic y tienes todas las cosas buenas de .net como gestión automática de memoria, recolección de elementos no utilizados y seguridad de tipos

Pero algunas veces algo sale más y aun teniendo la gestión automática de memoria de .net nos podemos encontrar con problemas, es por eso que hoy vamos a ver cómo podemos identificar estos problemas con WinDBG y sos para Silverlight.

Voy a usar como ejemplo el codigo subido por el usuario del foro de Silverlight.net. Puedes descargarlo desde aquí.

Lo primero de todo necesitamos ejecutar nuestra aplicación en modo release. Esto es importante porque hay pequeñas diferencias entre el modo debug y el release. Una vez que tenemos la aplicación ejecutándose es tiempo de WinDGB.

Si tu navegador es Windows Internet Explorer 8 y estás ejecutándolo sobre Windows 7 o Vista, sabrás que IE ejecuta cada tab en un proceso separado y por eso primero tienes que identificar cual es el proceso de IE que está ejecutando el código, en mi caso es el proceso 7958.

Con WinDBG abierto (puedes descargarlo de aquí) tienes que ir a File -> Attach to process (F6), y selecciona la id de tu proceso (en mi maquina es 7958), inmediatamente aparecerá en la ventana de salida toda la información básica de depuración. Teniendo en cuenta que nuestra aplicación es una aplicación administrada y WinDBG está diseñado para depurar aplicaciones nativas necesitamos una extensión del depurador para trabajar con aplicaciones administradas. Lo que necesitamos es SOS (Son of Strike) que está localizado en C:\Program Files (x86)\Microsoft Silverlight\4.0.50401.0\sos.dll. Para cada version de silverligh hay una versión de SOS, así que depende de la versión de Silveright que estés depurando tendrás que usar una u otra.

Para cargar SOS escribimos

.load C:\Program Files (x86)\Microsoft Silverlight\4.0.50401.0\sos.dll

Lo siguiente que necesitamos encontrar es una direccion valida del tipo que estamos buscando SilverlightVisualTreeRemovalFail.SilverlightControl1 y para eso tenemos que usar el comando !dumpheap para volcar todos los tipos filtrados por este tipo.

!dumpheap -type SilverlightVisualTreeRemovalFail.SilverlightControl1

0:005> !dumpheap -type SilverlightVisualTreeRemovalFail.SilverlightControl1

Address MT Size

087aad6c 04a45230 92

087ab460 04a45230 92

087ab6f0 04a45230 92

087ac01c 04a45230 92

087ac710 04a45230 92

087ace04 04a45230 92

087ad4f8 04a45230 92

087adbec 04a45230 92

087ae2e0 04a45230 92

087ae9d4 04a45230 92

087af0c8 04a45230 92

087af7bc 04a45230 92

087afeb0 04a45230 92

087b05a4 04a45230 92

087b0c98 04a45230 92

087b138c 04a45230 92

087b1a80 04a45230 92

087b2174 04a45230 92

087b2868 04a45230 92

087b2f5c 04a45230 92

087b3650 04a45230 92

087b3d44 04a45230 92

087b4438 04a45230 92

087b4b2c 04a45230 92

087b5220 04a45230 92

087b5914 04a45230 92

087b6008 04a45230 92

087b66fc 04a45230 92

087b6df0 04a45230 92

087b74e4 04a45230 92

087b7bd8 04a45230 92

087b82cc 04a45230 92

087b89c0 04a45230 92

087b90b4 04a45230 92

087b97a8 04a45230 92

087b9e9c 04a45230 92

087ba590 04a45230 92

087bac84 04a45230 92

087bb378 04a45230 92

087bba6c 04a45230 92

087bc160 04a45230 92

087bc854 04a45230 92

087bcf48 04a45230 92

087bd63c 04a45230 92

087bdd30 04a45230 92

087be424 04a45230 92

087beb18 04a45230 92

087bf20c 04a45230 92

087bf900 04a45230 92

087bfff4 04a45230 92

En la ventana de salida encontramos direcciones del tipo que hemos solicitado, seleccionamos una 087b1a80 y buscamos que objetos están referenciando este objeto (esto es lo que está causando que el objeto no sea recolectado) escribiendo esto:

!gcroot 087b1a80

0:005> !gcroot 087b1a80

Note: Roots found on stacks may be false positives. Run "!help gcroot" for

more info.

Scan Thread 5 OSTHread 10e8

Scan Thread 22 OSTHread 1f8

Scan Thread 23 OSTHread 1588

DOMAIN(07134BE0):HANDLE(Pinned):4a912f8:Root: 09784260(System.Object[])->

08796c78(System.Collections.Generic.Dictionary`2[[System.IntPtr, mscorlib],[System.Object, mscorlib]])->

09788260(System.Collections.Generic.Dictionary`2+Entry[[System.IntPtr, mscorlib],[System.Object, mscorlib]][])->

087b1e90(System.Windows.Controls.ControlTemplate)->

087b1a80(SilverlightVisualTreeRemovalFail.SilverlightControl1)

Encontramos que el objeto (087b1a80) está referenciado por otro objeto y en lo alto de la lista podemos encontrar cual es el objeto que lo está referenciando.

Ahora que hemos identificado que el objeto está referenciado por un GCHandle pineado el recolector siempre encontrará un camino hasta este objeto haciendo que nunca sea recolectado. Como el código que controla esta funcionalidad es de Microsoft no podemos hacer nada al respecto, pero en caso de que sea nuestro lo que podemos hacer es simplemente eliminar las referencias para que el objeto sea recolectado.

Además podemos volcar todos los tipos que hay en el heap y abrirlo con el CLRProfiler usando !traverseheap.

Saludos.

Luis Guerrero.

El player de Tele5 es ahora un Microsoft Case Study

Hola a todos!

Trabajar como desarrollador no es fácil, los cliente están siempre nerviosos y quieren tener su software a tiempo siempre. Así que cuando descubres que el software que tú has hecho se ha convertido en un caso de éxito hay que contárselo a todo el mundo!

Unos meses atrás empezamos un reproductor de video en Silverlight para Tele5. Querían más flexibilidad para publicar su contenido, así que empezamos este reproductor de video. Empezamos antes de que MEF existiera, así que tuve que implementar mi propia arquitectura de plug-ins basada en conceptos similares a los que tiene MEF.

Así que aquí os dejo toda la información del caso de estudio y por supuesto un enlace al player para que lo podáis disfrutar.

http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?casestudyid=4000007022 (EN)

http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?casestudyid=4000007045 (ES)

http://www.informativos.telecinco.es/

Saludos a todos!

Luis Guerrero.

Lanzamiento de Visual Studio 2010 – La importancia de la concurrencia

Hola a todos!

Dentro de poco empieza la gira de lanzamiento de Visual Studio 2010 por España y en este Lanzamiento tendré el honor de participar con una charla sobre la importancia de la computación paralela, así que espero veros a todos el día 13 de Abril en Barcelona y el 20 de Abril en Madrid.

Mientras podéis ir echando un vistazo al material sobre concurrencia de una charla anterior aquí.

Saludos!

Luis Guerrero.