In this series of posts I'll walk you through the primary features of the CLRProfiler for the .Net Compact Framework. The profiler contains numerous ways to analyze data about the GC heap so instead of briefly touching on all of them, I'll go into depth on the views I've found most useful.
We'll be looking at the profiler by way of an example, as I've found that learning a new tool is often easier if you have a specific problem to solve rather than just looking at the tool's features without any context. If you'd like more information on a view that I don't cover here you can read the document that ships with the full Framework's version of the profiler.
Our Sample
The sample I'll use to describe the profiler is the beginnings of a game I started to write using the Compact Framework. All the game currently does is allow you to start a new game and to rotate a set of blocks on the screen. Here's a simple view of the application:
The performance problem I'm having with this game involves my drawing logic. The blocks on the screen draw very slowing. On my Dell Axim I can literally see each column of blocks paint individually. Throughout these posts I'll use the CLRProfiler to figure out what I can do to make my game paint more quickly.
Launching an Application with the CLRProfiler
The CLRProfiler ships in the .Net Compact Framework Power Toys package. After installing the Power Toys you can find the CLRProfiler executable (NetCFClrProfiler.exe) in the bin directory of the .Net SDK. On my machine that directory is c:\Program Files\Microsoft.Net\SDK\CompactFramework\v3.5\bin. The Power Toys setup program also adds a menu item for the profiler to the Windows Start menu.
The main window of the profiler is strikingly simple:
Through this main window you can start and stop applications, take snapshots of the GC heap, and control various profiling options. These options include control over whether profiling is currently active and whether allocations, calls or both are logged.
Clicking the "Start Application…" button displays the following form:
On this form you enter the name of the device you'd like to connect to, the fully qualified path to the device executable you'd like to profile, and any command line parameters to be passed to the application. The CLRProfiler supports profiling applications on devices connected either over ActiveSync or TCP/IP. You can also profile applications running on emulators. The profiler supports the same types of devices that the .Net Compact Framework Performance Monitor does(in fact, the device selection and connectivity mechanisms are shared between the two tools).
In my example I have a device connected over ActiveSync and the name of my application is box.exe. Selecting "Connect" from the launch dialog starts the application on device and begins profiling. At this point just run your application as you normally would. The CLRProfiler causes your application to run much slower than normal. In order to speed up the debugging process you can turn profiling on and off for different sections of your application using the "Profiling active" checkbox on the profiler's main form.
When you're done profiling your application, you can stop it either by selecting the "Kill Application" button on the main form of the CLRProfiler or by just closing the application directly on the device.
The Summary Form
After your application exits the CLRProfiler displays the following summary form:
The summary form provides some general statistics about the use of managed memory as your application ran:
There are several buttons in this box that launch viewers that allow you to analyze data in various ways. You can view data in histograms based on object size, age, address and so on. I'll describe most of these views in detail in subsequent posts.
Getting back to our example, there are several pieces of data on this form that concern me, or are unexpected. The key to analyzing performance data such as this is not just looking at the raw values, but in interpreting the values in the context of what your application was doing as it was being profiled. For example, I profiled the time my application spent painting, yet I see that 5 garbage collections occurred and I created over 6 MB worth of objects. This data leads me to believe that I'm making the garbage collector work harder than it should for my scenario. Clearly there shouldn't be so much activity going on in the managed heap while I'm painting boxes on the screen!
In my next post, we'll use some of the histogram views to see how many objects my application is creating and of what type they are.
Thanks,
Steven
This posting is provided "AS IS" with no warranties, and confers no rights.