Using .NET Compact Framework Performance Counters


Performance testing and tuning are not confined only to measuring the execution time of the code. Performance also depends on the working set of the application. This includes the amount of memory allocated and de-allocated while the application executes. The presence of the .NET Compact Framework garbage collector makes it difficult to calculate how much memory is used and recycled as the application executes. The .NET Compact Framework's execution engine provides a small window into an application's working set.

The .NET Compact Framework's execution engine has the ability to keep track of several performance statistics as your application runs. These statistics include how much memory is allocated, how much memory was garbage collected, the number of P/Invokes, and so on. By default, this information is not collected or displayed to the user , but with some registry tweaking these performance counters can be turned on.

Turn On the .NET Compact Framework Performance Counters

The .NET Compact Framework performance counters are controlled by a registry key setting. The registry key is

 
 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETCompactFramework\PerfMonitor 

The DWORD registry value is " Counters ." The Counters value can be either zero or one. Setting the value to zero turns the performance counters off, while setting the value to one turns them on. If this registry key and value are not present, then the performance counters are off. This is the default state of the .NET Compact Framework when it is installed on the device.

When the execution engine is first invoked, it checks the value of this registry key. If the value is one, the performance counters are collected. The registry key is checked at startup time only. Thus, changing the registry value after the execution engine is started will not change its behavior until it is shut down and restarted.

Viewing the Performance Counters

To view the performance counters, set the registry key to one and then kick off any .NET Compact Framework application. When your application is done executing, the execution engine will output a file named mscoree.stat to the root directory of the device. This is a plain text file that contains the values of the performance counters collected during the run of the application. See Figure 15.1 for an example of the mscoree.stat file.

Figure 15.1. An mscoree.stat file is generated by the execution engine.

graphics/15fig01.jpg

Understanding the Performance Counters

There are thirty performance counters, and, despite their descriptive names , their meanings are not all self-evident. The performance counters can be divided into five groups using the information they collect as the division criteria. Table 15.1 describes the five counter groups and the information they collect.

Table 15.1. The .NET Compact Framework Performance Counter Groups

COUNTER GROUP

INFORMATION COLLECTED

Execution Time

The execution time of the application and execution engine startup

Allocation

Characteristics of memory allocation

Collection

Characteristics of the memory collected by the garbage collector

JIT Compilation

Characteristics of the Just-In-Time (JIT) compiler and the code it generates

Method Call

Characteristics of the methods called while the application ran

Measuring Application Execution Time Characteristics

The counters in the Execution Time group measure how long the application and execution engine executed. This includes total application runtime and execution engine startup time. The following list describes the counters in the Execution Time group:

Execution Engine Startup Time This counter measures the time from when the execution engine first gets control, after the OS has loaded the EXEs and DLLs, to when the execution engine is about to call the main method of the application. This time, which does not include creating and initializing the application's static objects, is measured in milliseconds . The values n, mean, min, and max are not collected for this counter.

Total Program Run Time The time from when the execution engine first gets control to when the execution engine terminates. The time is measured in milliseconds. The values for n, mean, min, and max are not collected for this counter.

Measuring Allocation Characteristics

The counters in the Allocation group measure memory allocation characteristics. These counters measure memory in terms of byte as well as objects, but the counters do not provide information on what types of objects were allocated.

Peak Bytes Allocated This counter measures the largest number of bytes allocated at once. The values n, mean, min, and max are not collected for this counter.

Number Of Objects Allocated This is the total number of objects allocated by the execution engine. This includes every object that was created while the program was executing. The values n, mean, min, and max are not collected for this counter. This counter is measured in objects.

Bytes Allocated The number of bytes allocated for all of the objects allocated in the system. The value n is the number of objects allocated. The mean value is the mean number of bytes allocated per object. The min value is the size of the smallest object. The max value is the size of the largest object allocated. All values except n are measured in bytes. The n value is measured in objects and should be equal to the value of the Number of Objects Allocated counter.

Using the Counters in the Collection Group

The Collection counters collect information about the operations performed by the garbage collector (GC). This is the largest group of counters. The GC does three types of collections, and there are four counters collected for each type of collection. See the "Understanding the .NET Compact Framework's Garbage Collector" section for a description of each type of collection. The total amount of time spent in the GC is also tracked. The following list describes the many counters in the Collection group:

Number Of Simple Collections This counter measures the number of simple collections performed by the garbage collector during the execution of the application. See the section titled "Understanding the .NET Compact Framework's Garbage Collector" for a description of a simple collection. The values n, mean, min, and max are not collected for this counter.

Bytes Collected By Simple Collection This counter measures the total number of bytes freed during all of the simple collections that occurred during the program run. The n value is the number of simple collections that occurred and should be equal to the value of the Number of Simple Collections counter. The mean, min, and max values are self-explanatory.

Bytes In Use After Simple Collection This counter measures the sum of all the bytes that were still actively being referenced after each simple collection. The n value is the number of simple collections that occurred and should be equal to the value of the Number of Simple Collections counter. The mean, min, and max values are self-explanatory.

Time In Simple Collect This counter measures the total amount of time spent by the garbage collector doing simple collections. This counter is measured in milliseconds, and the n , mean, min, and max values are not collected.

Number Of Compact Collections Measures the total number of compact collections that occurred during application execution. See the section titled "Understanding the .NET Compact Framework's Garbage Collector" for a description of a compact collection. The values n, mean, min, and max are not collected for this counter.

Bytes Collected By Compact Collections This one measures the total number of bytes freed during all of the compact collections that occurred during application execution. The n value is the total number of compact collections that occurred and should be equal to the value of the Number of Compact Collections counter. The mean, min, and max values are self-explanatory.

Bytes In Use After Compact Collection This counter measures the sum of all the bytes that were still actively being referenced after each compact collection occurred. The n value is the number of compact collections that occurred and should be equal to the value of the Number of Compact Collections counter. The mean, min, and max values are self-explanatory.

Time In Compact Collect This counter measures the total amount of time that the garbage collector spent making compact collections. This counter is measured in milliseconds. The values n, mean, min, and max are not collected for this counter.

Number Of Full Collections This is the total number of full collections carried out by the garbage collector during application execution. See the section titled "Understanding the .NET Compact Framework's Garbage Collector" for a description of a full collection. The values n, mean, min, and max are not collected for this counter.

Bytes Collected By Full Collection This counter measures the total number of bytes freed during all of the full collections that occurred during application execution. The n value is the total number of full collections that occurred and should be equal to the value of the Number of Full Collections counter. The mean, min, and max values are self-explanatory.

Bytes In Use After Full Collection This counter measures the sum of all the bytes that were still actively being referenced after each full collection occurred. The n value is the number of full collections that occurred and should be equal to the value of the Number of Full Collections counter. The mean, min, and max values are self-explanatory.

Time In Full Collection This tool measures the total amount of time that the garbage collector spent executing full collections. This counter is measured in milliseconds. The values n, mean, min, and max are not collected for this counter.

GC Number Of Application Induced Collections This counter measures the number of collections that were manually invoked by the application by calling GC.Collect . The values n, mean, min, and max are not collected for this counter.

GC Latency Time This counter measures the total amount of time spent by the garbage collector making all collections during the application execution. The values n, mean, min, and max are not collected for this counter.

Total Bytes In Use After Collection The peak memory, managed and unmanaged, in use by the application as measured immediately following each garbage collection. The n value is the number of garbage collections that occurred during application execution. The mean, min, and max values are self-explanatory.

Discovering JIT Compiler Performance Characteristics

The execution engine also collects information about the JIT compiler. This includes information about the code it compiled as well as the code it pitched. The term pitching means to remove JIT-compiled code from the code cache, an in-memory cache for JIT-compiled code. This provides fast access for methods called more than once because they need to be compiled on only the first method call. Subsequent calls will execute the JIT-compiled code in the code cache. That said, code pitching will actually slow your application down because cached methods that were pitched will need to be recompiled the next time they are called. The following list describes the counters in the JIT Compilation group:

Bytes Jitted This counter measures the total amount of MSIL code that was Just-In-Time compiled. The n value is the number of methods jitted and should be equal to the Number of Methods Jitted counter. The mean value is the mean number of bytes jitted per method. The min value is the smallest number of bytes jitted in one method, and the max value is the largest number of bytes jitted in one method.

Native Bytes Jitted This tool measures the total amount of native instructions created while jitting the MSIL of the application. The n value is the number of methods jitted and should be equal to the Number of Methods Jitted counter. The mean value is the mean number of native instructions, in bytes, created per method. The min value is the smallest number of native instructions, in bytes, created by jitting a method. The max value is the largest number of native instructions, in bytes, created by jitting a method.

Number of Methods Jitted This counter measures the total number of methods jitted during the program run. The values n, mean, min, and max are not collected for this counter.

Bytes Pitched This one counts the total number of native instructions, measured in bytes, released from memory after being Just-In-Time compiled. The values of n, mean, min, and max are not collected for this counter.

Number of Methods Pitched This counter measures the total number of methods released from memory after having been Just-In-Time compiled. The values n, mean, min, and max are not collected for this counter.

Measure Method Call Characteristics

The execution engine can also collect information about the method calls and exceptions thrown. The counters in the Method Call group retain this information, as described in this list:

Number of Exceptions This counter measures the number of exceptions that were thrown during application execution. Values for n, mean, min, and max are not collected for this counter.

Number of Calls Measures the number of calls that the JIT could make directly. This means the JIT could generate an instruction(s) resulting in a direct call to the method. Values for n, mean, min, and max are not collected for this counter.

Number of Virtual Calls This one measures the number of calls that the JIT could not make directly. This means that in order to call the method, the JIT first needed to compile the method and then determine how to call the method.

Number Of Virtual Call Cache Hits This counter measures how many virtual calls were resolved by the virtual call lookup cache. Values for n, mean, min, and max are not collected for this counter.

Number of PInvoke Calls This counter measures the total number of P/Invoke calls that were made during application execution. The values for n, mean, min, and max are not collected for this counter.

Total Bytes in Use After Collection The final counter measures the peak memory, managed and unmanaged, in use by the application as measured immediately following each garbage collection. The n value is the number of garbage collections that occurred during application execution. The mean, min, and max values are self-explanatory.

CALCULATING THE VIRTUAL CALL CACHE HIT RATE

Using the Number of Virtual Call Cache Hits counter and the Number of Virtual Calls counter, you can calculate the virtual call cache hit rate. This hit rate is the percentage of virtual calls that were resolved in the virtual call cache. The following formula can be used to find the virtual call cache hit rate:

(Number of Virtual Call Cache Hits / Number of Virtual Calls) x 100%

For example, if there were 5000 virtual calls and the virtual call cache was hit 4900 times, then the hit rate would equal 98%:

(4900/5000) x 100% = 98%

The higher the hit rate, the better, because virtual calls that were resolved in the cache have a smaller overall execution time.


Understanding the .NET Compact Framework's Garbage Collector

The .NET Compact Framework garbage collector uses a completely different algorithm from the desktop garbage collector when freeing memory. Whereas the desktop garbage collector uses an algorithm based on memory lifetimes and generations, the .NET Compact Framework has three different types of garbage collection that it will execute when memory is needed.

The first type of garbage collection is simple collection. This is the fastest algorithm the garbage collector uses to free memory. This algorithm is a basic mark-and-sweep algorithm. It passes through the memory, marking any memory that is being used and freeing that which is not.

The second type of garbage collection is compact collection. First a compact collection performs a simple collection to free any unused memory. Then the compact collection attempts to rearrange allocated memory into one contiguous block of memory. Since a compact collection includes a simple collection, the compact collection is a slower collection.

The third and slowest garbage collection algorithm is the full collection. In addition to a compact collection, the full collection will pitch code until there is enough free memory. Any code that is pitched will have to be re-jitted when it is needed again.

The garbage collector does not do all three collections every time memory is needed. The garbage collector will first run a simple collection and test whether enough memory has been released. If not, a compact collection is executed. If there still is not enough memory released, the garbage collector will finally run the full collection algorithm. If there is still not enough memory after a full collection, a System.OutOfMemoryException will be thrown.

The NetCF Performance Counter Explorer

In the support media of this book, in the directory for this chapter, you will find a Visual Studio .NET project file for the .NET Compact Framework Performance Counter Explorer. This is a desktop application that helps analyze the performance counters in the mscoree.stat file. To use this application, first create a mscoree.stat file and put it on a desktop computer. Next, start the .NET Compact Framework Performance Counter Explorer. Then load an mscoree.stat file by selecting the Open... menu option from the File menu. The open file dialog will appear. Find the mscoree.stat file and click the Open button. This will load the file into the performance counter table (see Figure 15.2). The table now contains all of the performance counters from the mscoree.stat files as well as all of their values.

Figure 15.2. A mscoree.stat file is loaded into the NetCF Perf Counter Explorer.

graphics/15fig02.jpg

Now click one of the performance counters. The description of the counter is displayed in the Counter Description area at the bottom of the application.

The second feature of the .NET Compact Framework Performance Counter Explorer is its ability to compare two mscoree.stat files. This comes in handy when attempting to measure the performance impact of a source code change. First, create a mscoree.stat file without the source code change and put it on the desktop computer. Next, apply the source code changes to your application and create another mscoree.stat file. Put this mscoree.stat file on the desktop computer as well. Then select the Compare... option from the File menu. The open file dialog will appear. Select the first mscoree.stat file to compare and click Open. Another open file dialog will appear. Now select the second mscoree.stat file to compare. Data will again be loaded into the Perf Counter table. The performance counter names will be the same, but the values have a different meaning. The values are now the differences between the first and second mscoree.stat files. This provides an easy way to view the differences between two different mscoree.stat files (see Figure 15.3).

Figure 15.3. The NetCF Perf Counter Explorer is now loaded to compare two mscoree.stat files.

graphics/15fig03.jpg

Selecting a performance counter will again display its description in the Counter Description area. The Perf Counter table displays only the differences between the values. You can get to the original values by double-clicking a performance counter or selecting the performance counter name and pressing Enter. This will display a window that contains the Value, N, Mean, Max, and Min values of the performance counter from both File One and File Two (see Figure 15.4).

Figure 15.4. The counter comparison dialog in the NetCF Perf Counter Explorer lets you directly compare the values from two files.

graphics/15fig04.jpg



Microsoft.NET Compact Framework Kick Start
Microsoft .NET Compact Framework Kick Start
ISBN: 0672325705
EAN: 2147483647
Year: 2003
Pages: 206

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net