Hunting down memory leaks in Silverlight
Recently, I was noticing some memory issues with a Silverlight application I was working on. I was creating a dialog window (user control) dynamically where the user could edit and save data. The dialog user control was data bound to a ‘ViewModel’ type which populates the data controls in the dialog and is then used to populate and save a business object. After, the user clicks on the OK or the Cancel button, i was disposing away with the user control from memory by setting its reference to NULL. But, when i repeated the process of opening and closing the dialog multiple times, the memory used by Internet Explorer always kept going up. This made me suspicious that even though I was setting the user control’s reference to NULL, the user control was never disposed away from memory.
To confirm that multiple instances of the user control were still in memory, I resorted to using “windbg”. Following the steps below, you can confirm and debug memory leaks in Silverlight and also in the .NET CLR.
- Download and install windbg from here.
- Run the Silverlight application and bring it to a state where you think a memory problem exists. In my case above, I had to open and close the suspect dialog multiple times.
- Run windbg and attach to the Internet Explorer process running your Silverlight application.
- Load the SOS debugging extension for Silverlight. This is installed with the Silverlight SDK on your system. The ‘SOS.dll’ is found under the Silverlight installation directory. For me it is at “C:\Program Files\Microsoft Silverlight\2.0.40115.0\sos.dll”. To load the SOS debugging extension execute the command “.load C:\Program Files\Microsoft Silverlight\2.0.40115.0\sos.dll” in the windbg window.
- Run the “!dumpheap -stat” command to view the objects in memory and the count of their instances.
- Run the “!dumpheap –stat –type [TypeName]” command to view the number of instances of the specified type in memory. In my case, I found that the number of instances of the dialog user control object in memory was always equal to the number of times I had opened and closed the dialog user control. This indicated that the user control object were not getting disposed from memory even when I had set its reference to NULL.
- Run the “!dumpheap –type [TypeName]” command to view all the memory addresses of the object’s instances.
- Run the “!gcroot [Address]” command to view how the instance of the object can be reached. In other words, it tells us what is holding on to the reference of the object and thus keeping the object in memory without being cleaned up by the garbage collector. The output here is hard to read, but the pain of going through this exercise will definitely pay off when the memory leak in the application has been fixed.
In my case, it turned out that the ‘ViewModel’ object the dialog user control was being data bound to was holding on to a reference to the user control object. So, to fix the memory leak, all I had to do was to set the ‘DataContext’ property of the user control to NULL before setting the user control reference itself to NULL.