So I have been looking for a memory pressure issue with an application running on Windows Mobile and Compact Framework. The applicaion was going "live" for expanded testing on April 2nd with 1500 testers. We knew we had a memory issue but finding it was nearly impossible until Compact Framework 2.0 SP2.0 come out.
Prior to SP2 we had thought we had it narrowed down to native memory not being freed. After all the code disposed of all forms and objects so what else could it be. With the release of SP2 however I just knew I could prove now that it was a 3rd party API causing the problem. So I fired up the new improved Remote Process Monitor and look for memory not being freed.
If you click on the image you will see a new button at the bottom of the window next to the disconnect button called "View GC Heap". This button allows you to view objects by type that are allocated in memory.
When you first push the button you will see a display of all your types and objects. Clicking on a check box next to the types you want to see displayed as objects. The object list allows you to see the types and amount of memory being consumed by that type. You can change what objects are listed by hiting the refresh button and walk the object tree by type.
You can also click the column headers and get the list sorted from largest to smallest on memory usage for example. At first blush it looked like all those byte arrays where my issue! Ha the un-reclaimed memory or so I thought. I selected the first row in the table, held the shift key down and pushed the end key. I had highlighted all the rows. Next I clicked the check box making everything checked and then clicked it again to unchecked everything. Next I clicked on just the row of the type I wished highlighted and clicked just its check box. Finally I clicked the refresh tree button.
Well imagine my surprise and chagrin when the bytes turned out to be from our custom configuration manager and the XML parser. Further tests showed that while a large chunk of memory was consumed by the XML nodes it was neither shrinking or growing. In fact our custom button class was consuming memory without being freed. What the heck!
A quick check of the code showed that the forms were being freed. The only discrepancy was the forms were not being closed by our Navigation component. So why were the forms not being freed? Turns out in using a registry notification the event handler was only being removed when the form was closed. This caused the forms to be held in memory by the registry notification control. Changing the close code to be in the form's dispose fixed the problem and the memory leak was gone!
Remote Performance Monitor made finding what had been a multiple week debug session solved in a couple of hours. Thank you Compact Framework team for this invaluable tool.
Comments