In the first post of this series, I talked about how to enable collection of performance counter data in the .NET Compact Framework.  In this installment, I'd like to talk a bit about the data collected by version 1 of the .NET Compact Framework.

The table below lists the performance data collected by version 1 of the .NET Compact Framework.  For convenience of discussing the counters, I have grouped them by category (Garbage Collector, etc).

Execution Engine
  Execution Engine Startup Time
  Total Program Run Time
Garbage Collector
  Peak Bytes Allocated
  Number Of Objects Allocated
  Bytes Allocated
  Number Of Simple Collections
  Bytes Collected By Simple Collection
  Bytes In Use After Simple Collection
  Time In Simple Collect
  Number Of Compact Collections
  Bytes Collected By Compact Collection
  Bytes In Use After Compact Collection
  Time In Compact Collection
  Number Of Full Collections
  Bytes Collected By Full Collection
  Bytes In Use After Full Collection
  Time In Full Collection
  Number Of Application Induced Collections
  Total Bytes In Use After Collection
IL
  Bytes Jitted
  Native Bytes Jitted
  Number Of Methods Jitted
  Bytes Pitched
  Number Of Methods Pitched
  Number Of Exceptions
  Number Of Calls
  Number Of Virtual Calls
  Number Of Virtual Call Cache Hits
  Number Of PInvoke Calls

The mscoree.stat file includes running totals, count (n), average (mean), minimum and maximum values for the above mentioned counters.  I've included an example file below.  For counters where count, mean, minimum and maximum data is not relevant (ex: Total Program Run Time) a value of zero (0) is logged.

The sections below discuss each counter in the mscoree.stat file.  I will use the following format for the discussions.
Counter name
Brief description of the counter
Discussion of the contents of relevant columns (value, n. mean, min, max)
Any additional comments relating to the counter

Execution Engine Counters
In version 1 of the .NET Compact Framework, there are two Execution Engine counters:  Execution Engine Startup Time and Total Program Run Time.

Execution Engine Startup Time
Time to get to your application's entry point (Main).
value: Time in milliseconds
This counter is not of use to application writers and has been removed from version 2 of the .NET Compact Framework.

Total Program Run Time
Total application run time, including Execution Engine startup.
value: Time in milliseconds

Garbage Collector Counters
Many of the Garbage Collector counters are related to a collection type (simple, compact, full).  For information on the .NET Compact Framework Garbage Collector, please see Steven Pratschner's post: An Overview of the .NET Compact Framework Garbage Collector.  In the discussion below, substitute <type> with Simple, Compact or Full depending on which counters you are examining.

Number Of <type> Collections
This counter reports the number of garbage collections (of the specified type) that occurred during your application's run time.
value: Garbage collection count

Bytes Collected By <type> Collection
The total number of bytes that were collected by the collections that occurred while your application ran. 
value: Running total of bytes collected
n: The number of collections
mean:  The average number of bytes collected during each collection
min: The smallest amount of bytes collected
max: The largest amount of bytes collected

Bytes In Use After <type> Collection
The total number of bytes in use, by managed objects, in your application, after garbage collection of the specified type occurs
value: Running total of bytes available after collection
n: The number of collections
mean:  The average number of bytes in use after collection
min: The smallest amount of bytes in use after collection
max: The largest amount of bytes in use after collection
The value column is an accumulation of total bytes after collection, it is not of much use when diagnosing performance issues.  This total is combined with the count of collections (n column) to compute the mean.  For this counter, the mean, min and max columns provide the useful data.

Time In <type> Collect
The time spent in all collections of the specified type.
value: Running total of the time (in milliseconds) spent in collections
n: The number of collections
mean: The average length of time to perform the collection
min: The shortest length of time spent in collection
max: The longest length of time spent in collection

The following counters are related to the Garbage Collector as a whole, and not a specific collection type.

GC Number Of Application Induced Collections
The number of garbage collections that occurred as a result of the application calling GC.Collect().
value: The number of collections
For a detailed discussion of the issues surrounding GC.Collect(), please see Scott Holden's post: The perils of GC.Collect.

GC Latency Time
The time spent in all collections of all types.
value: Running total of the time (in milliseconds) spent in collections
n: The number of collections
mean: The average length of time to perform the collection
min: The shortest length of time spent in collection
max: The longest length of time spent in collection

Total Bytes In Use After Collection
The total number of bytes in use, by managed objects, in your application, after garbage collection of any type occurs
value: Running total of bytes available after collection
n: Number of garbage collections
mean:  The average number of bytes in use after collection
min: The smallest amount of bytes in use after collection
max: The largest amount of bytes in use after collection
The value column is an accumulation of total bytes after collection, it is not of much use when diagnosing performance issues.  This total is combined with the count of collections (n column) to compute the mean.  For this counter, the mean, min and max columns provide the useful data.

Bytes Allocated
The amount of memory allocated for managed objects, Just-In-Time compiled code and runtime data structures during the run time of your application.
value: Running total of bytes allocated
n: Number of allocations
mean: Average allocation size
min: Size of smallest allocation
max: Size of largest allocation
Please note that memory allocated by P/Invoke calls is not tracked as a part of this counter.

Peak Bytes Allocated
The maximum amount of memory allocated for managed objects, Just-In-Time compiled code and runtime data structures, at any time during the run time of your application.
value:  The largest number of bytes used by the application
I find this to be one of the most useful performance counters.  By tracking peak memory usage across multiple application runs (where the same scenario is performed), memory consumption related issues can be identified at a high level.
Please note that memory allocated by P/Invoke calls is not tracked as a part of this counter.

Number Of Objects Allocated
The number of managed objects allocated by your application.
value: Running total of allocated objects
This counter includes object that have been disposed / collected.

IL Counters

The counters in this section are related to the .NET Compact Framework's Just-In-Time (JIT) compiler.

Bytes Jitted
The pre-compile size of the IL code being Just-In-Time compiled.
value: Running total of bytes compiled
n: Number of compilations
mean: Average number of bytes in each compilation
min: Smallest number of bytes compiled
max: Largest number of bytes compiled

Native Bytes Jitted
The post-compile size of the IL code being Just-In-Time compiled.
value: Running total of bytes compiled
n: Number of compilations
mean: Average number of bytes in each compilation
min: Smallest number of bytes compiled
max: Largest number of bytes compiled

Number Of Methods Jitted
A count of methods which have been Just-In-Time compiled.
value: Running total of compiled methods

Bytes Pitched
Number of bytes removed from the code cache.
value: Running total of removed bytes
n: Number of times code was removed from the cache
mean: Average size of the removed code
min: Size of smallest code removal
max: Size of largest code removal
This counter will show non-zero data only if the application has encountered extreme memory pressure.

Number Of Methods Pitched
Number of jitted methods removed from the code cache.
value: Running total of removed methods
n: Number of times code was removed from the cache
This counter will show non-zero data only if the application has encountered extreme memory pressure.

Number Of Exceptions
Number of managed exceptions thrown while the application was running.
value: Running total of thrown exceptions

Number Of Calls
Number of direct calls to managed methods.
value: Running total of method calls
It is important to note that the calls collected in this counter do not include calls to virtual methods.  Virtual method calls are collected in the Number Of Virtual Calls counter.

Number Of Virtual Calls
Number of virtual calls to managed methods.
value: Running total of method calls

Number Of Virtual Call Cache Hits
Number of virtual calls to methods which have been cached.
value: Running total of virtual method calls from the cache
The value in this counter will often be very close to the value of the Number Of Virtual Calls counter.  Where these counter values differ is in the initial call (including re-calls after a method is pitched).

The Number Of PInvoke Calls
The number of calls into native functions made (via P/Invoke) by your application.
value: Running total of native function calls

Example mscoree.stat file
The following is an example mscoree.stat file that shows the data collected from a simple application.  The garbage collections in this application were caused by moving it to the background (running a second application in the foreground).

counter value n mean min max
Execution Engine Startup Time 11278 0 0 0 0
Total Program Run Time 333223 0 0 0 0
Peak Bytes Allocated 214563 0 0 0 0
Number Of Objects Allocated 2928 0 0 0 0
Bytes Allocated 116256 2928 39 8 1296
Number Of Simple Collections 0 0 0 0 0
Bytes Collected By Simple Collection 0 0 0 0 0
Bytes In Use After Simple Collection 0 0 0 0 0
Time In Simple Collect 0 0 0 0 0
Number Of Compact Collections 0 0 0 0 0
Bytes Collected By Compact Collections 0 0 0 0 0
Bytes In Use After Compact Collection 0 0 0 0 0
Time In Compact Collect 0 0 0 0 0
Number Of Full Collections 3 0 0 0 0
Bytes Collected By Full Collection 62800 3 20933 14504 25800
Bytes In Use After Full Collection 139876 3 46625 41068 49640
Time In Full Collection 106 3 35 31 38
GC Number Of Application Induced Collections 0 0 0 0 0
GC Latency Time 106 3 35 31 38
Bytes Jitted 24699 414 59 1 2109
Native Bytes Jitted 78900 414 190 24 4708
Number of Methods Jitted 414 0 0 0 0
Bytes Pitched 0 0 0 0 0
Number of Methods Pitched 0 0 0 0 0
Number of Exceptions 0 0 0 0 0
Number of Calls 12198 0 0 0 0
Number of Virtual Calls 4084 0 0 0 0
Number of Virtual Call Cache Hits 3996 0 0 0 0
Number of PInvoke Calls 969 0 0 0 0
Total Bytes In Use After Collection 541953 3 180651 179219 181787

Recommended reading
For anyone building applications on the .NET Compact Framework, I highly recommend the reading the following:

.NET Compact Framework version 2.0 Performance and Working Set FAQ - by Roman Batoukov
This article (on the .NET Compact Framework Team weblog) is very thorough and covers many performance issues and how to avoid them.  While the article specifically talks about version 2 of the .NET Compact Framework, many of its recommendations apply to version 1 as well.

When Performance Matters and The Perils of GC.Collect (or when to use GC.Collect) - by Scott Holden

.NET Compact Framework Advanced Memory Management - by Mike Zintel

An Overview of the .NET Compact Framework Garbage Collector - by Steven Pratschner


I'll be posting on the .NET Compact Framework version 2 performance counters soon.  Given the length of this post, and the larger number of counters in version 2, I will likely split the discussion into multiple (smaller) posts around counter categories.

Take care,
-- DK

[Edit: post title]

Disclaimer(s):
This posting is provided "AS IS" with no warranties, and confers no rights.