This post is a collection of my findings from a recent effort to eliminate memory leaks in a .NET Compact Framework (CF .NET) application. All of the information in this post is available elsewhere on the web but after spending a lot of time pulling it all together for my own purposes I thought I might write up my findings and maybe save someone else a few hours of time down the road. The majority of this post will focus on the initial setup needed to even get to the point that you can start to profile memory usage and find leaks in a running CF .NET application as I found that to be the most confusing and frustrating part of the entire process.
I’ve found that the .NET Compact Framework Remote Performance Monitor tool is the most memory profiling tool available for the purposes of finding memory leaks. Here are a couple of very informative blog posts by Steven Pratschner describing how this tool can be used:
1. Setup A Windows Mobile Emulator Image
If you already use a Windows Mobile emulator image for doing CF .NET development then you should be able to just use that same image to profile memory usage and find leaks. If you don’t currently use an emulator image you’ll need to set one up and get to the point that you can deploy and run your app on the emulator. You might at this point ask why you can’t do this on a physical device. You can do it on a physical device but I’ve opted to use an emulator for a few reasons:
- Most physical devices that I have access to run Windows CE and I have not yet been able to get the memory profiling tool I prefer to use to work with Windows CE.
- I wanted to make this easy to setup for other members of the development team that I work on so that others will be able to work on memory leak issues in the future.
- Generally speaking I’ve found it’s easier to fire up an emulator image and start working than to mess with cradling a physical device.
If you need to setup an emulator image to work with, start out by grabbing some from here: Windows Mobile 6.1.4 Emulator Images. Download the ‘Professional Images’ package from that site and install it. Once installed you should be able to start, cradle, and deploy your application to a running emulator image.
2. Install Hotfix KB 2436709 for .NET Compact Framework 3.5
Once you have an emulator that can run the application you want to profile, you’ll need to install a hotfix to the Compact Framework in order to let the Remote Performance Monitor take snapshots of the garbage collected heap while the application is running. These snapshots are what ultimately let you see what objects are leaking as the application runs. You can request and download this hotfix here: http://support.microsoft.com/kb/2436709
Once downloaded, cradle the emulator and copy the .cab file over to the emulator and run it on the device to install over the existing .NET Compact Framework on the device.
3. Install The .NET Compact Framework Remote Performance Monitor
The Remote Performance Monitor tool comes with the Power Toys for .NET Compact Framework 3.5 package. You can download this package here: http://www.microsoft.com/en-us/download/details.aspx?id=13442
It’s worth nothing here that I also took a look at the CLR Profiler tool which also ships with the Power Toys package. This tool was easier to get setup than the Remote Performance Monitor, but I found it really hard to parse the resulting output for an app as large and complicated as the one I was profiling. Also, taking snapshots with this tool was painfully slow to the point that it wasn’t really practical for me to use. As always, your mileage may vary.
4. Deploy And Profile Your Application
Once you have an emulator image that can run your application and has the properly hot-fixed version of the .NET Compact Framework installed you’re ready to start profiling your application with the remote performance monitor. The blog posts that I linked to at the top of this article have a lot of detailed and helpful information about this, but I’ll summarize it here as well.
First, make sure that your emulator is cradled and that the application you want to profile is available on the emulator. Also be sure that no applications are currently running on the emulator.
Next, start the Remote Performance Monitor and click the green ‘Play’ icon to start and profile an application. This brings up the ‘Launch Application’ dialog:
From this dialog you’ll select the device that you want to profile the application on. If you’ve setup an emulator for this you should have an option like ”Pocket_PC (ActiveSync)” in this list. You’ll also need to specifiy the path to the application that you want to profile on the device. If your app lives under the “Program Files” path in a sub folder called “Myapp” you would enter: “\Program Files\MyApp\MyApp.exe”. You can optionally specify a path on the desktop from which to copy the application, but I’ve always found it easier to just have the application already deployed and available on the emulator. Finally, enter any startup arguments that your application might need and then click ‘OK’ to launch and start profiling the app.
5. Take and Compare GC Heap Snapshots
Once your app is running and being profiled the main Performance Monitor Window will start being constantly updated with a wide variety of metrics. There are a lot of interesting metrics here and most of them line up with counters that you can setup and monitor in PerfMon for Windows applications on a desktop or server. For the purposes of finding memory leaks, however, we’re primarily concerned with the ‘GC Heap’ button that will become available in the main toolbar of the Performance Monitor.
Clicking the ‘GC Heap’ button will force a garbage collection on the running application and then take a snapshot of the garbage collected heap. This snapshot lets you see all objects that the garbage collector wasn’t able to clean up. As you use your application and keep taking snapshots you can start to see if certain types of objects keep getting higher and higher instance counts which is a pretty good indication that you have a leak somewhere. The Finding Memory Leaks using the .NET CF Remote Performance Monitor blog post that I linked to at the start of this post has a lot more information and a good example of how to do this.