Implementing Performance Counters That Require a Base Counter

Implementing Performance Counters That Require a Base Counter


You need to use some of the more advanced performance counters to accurately track information about your application. The performance counters exist as two counters used together. The first counter is the main counter, which is divided by the second counter, called the base counter. Essentially, the first counter is the numerator and the second counter is the denominator; the custom counter reports the result of this division operation. The main counter is used in tandem with its base counter type to calculate, for example, the average amount of time it takes for an action (e.g., connecting to a server) to complete or the average number of actions that occur during a single process (e.g., database timeouts).


Create a complex performance counter, which is used in tandem with the base counter type to calculate, for example, the average amount of time it takes for an action to complete or the average number of actions that occur during a single process. Use the CreateComplexCounter method shown in Figure to create a complex custom counter.

Creating a complex counter

public void CreateComplexCounter(string counterName, string counterHelp,
    PerformanceCounterType counterType, string baseCounterName,
    string baseCounterHelp, PerformanceCounterType baseCounterType,
    string categoryName, string categoryHelp,
    out PerformanceCounter appCounter,
    out PerformanceCounter appBaseCounter)
    CounterCreationDataCollection counterCollection =
        new CounterCreationDataCollection( );

    // Create the custom counter object and its base counter object
    // and add them to the collection of counters (they must be
    // added successively).
    CounterCreationData counter = new CounterCreationData(counterName,
        counterHelp, counterType);
    CounterCreationData BaseCounter =
        new CounterCreationData(baseCounterName,
                baseCounterHelp, baseCounterType);

    // Create category.
    if (PerformanceCounterCategory.Exists(categoryName))

    PerformanceCounterCategory appCategory =
        PerformanceCounterCategory.Create(categoryName, categoryHelp,

    // Create the counter and initialize it.
    PerformanceCounter newappcounter =
        new PerformanceCounter(categoryName, counterName, false);
    PerformanceCounter newappbaseCounter =
        new PerformanceCounter(categoryName, baseCounterName, false);

    newappcounter.RawValue = 0;
    newappbaseCounter.RawValue = 0;

    appCounter = newappcounter;
    appBaseCounter = newappbaseCounter;


The CreateComplexCounter method returns two PerformanceCounter objects as out parameters; one is the counter, the other is the base counter. These two counters are used in tandem; the base counter controls some aspect of the denominator in the calculation relating these two counters. Since the value of the appCounter parameter, returned from this method, depends on the value in the appBaseCounter parameter, we are considering these types of counters as complex counters.

The ASPNET user account, as well as many other user accounts by default, prevent performance counters from being read. You can either increase the permissions allowed for these accounts or use impersonation with an account that has access to enable this functionality. However, this then becomes a deployment requirement of your application. Decreasing security for the ASPNET account or other user accounts may very well be frowned upon by IT folks deploying your application.

This method operates similarly to the CreateSimpleCounter method described in Recipe 8.11. The one major difference is that two CounterCreationData objects are created and added to the CounterCreationDataCollection object. This first CounterCreationData object is the main counter used in the calculation for this counter. The second is the base counter, used in the denominator of the calculation for this counter. These counters must be added, in order, to the CounterCreationDataCollection object. In addition, the counter defined by the counterName parameter must be added before the counter defined by the baseCounterName parameter.

The application can perform several actions on these PerformanceCounter objects. An application can increment or decrement a PerformanceCounter object using one of these three methods:

	long value = newappcounter.Increment( );
	long value = newappcounter.Decrement( );
	long value = newappcounter.IncrementBy(i);

	long value = newappbaseCounter.Increment( );
	long value = newappbaseCounter.Decrement( );
	long value = newappbaseCounter.IncrementBy(i);

	// Additionally, a negative number may be passed in to the IncrementBy method
	// to mimic a DecrementBy method (which is not included in this class).
	long value = newappcounter.IncrementBy(-i);
	long value = newappbaseCounter.IncrementBy(-i);

The first two methods accept no parameters, while the third accepts a long containing the number by which to increment the counter. All three methods return a long type indicating the new value of the counter.

In addition to incrementing or decrementing these counters, you can also take samples of these counters at various points in the application. A sample is a snapshot of the counter and all of its values at a particular instance in time. A sample may be taken using the following lines of code:

	CounterSample counterSampleValue = newappcounter.NextSample( );
	CounterSample counterSampleBaseValue = newappbaseCounter.NextSample( );

The NextSample method accepts no parameters and returns a CounterSample object.

At another point in the application, a counter may be sampled again, and the samples can be passed in to the static Calculate method on the CounterSample class. These actions may be performed in a single line of code as follows:

	float calculatedSample = CounterSample.Calculate(counterSampleValue,
	                                                 newappcounter.NextSample( ));

Note that you need to pass only the newappcounter samples; the newappbaseCounter samples are handled for you. The calculated sample calculatedSample may be stored for future analysis. See Recipe 8.11 for a definition of the Calculate method.

The complex performance counters defined in the .NET Framework are defined here:


Calculates the AverageTimer64 value change over the AverageBase value change. This counter uses AverageBase as its base counter type.


Calculates the AverageTimer32 value change over the number of ticks per second, all over the AverageBase value change. This counter uses AverageBase as its base counter type.


Calculates the percentage of CounterMultiTimer value change over the CounterMultiTimer time change divided by CounterMultiBase. This counter uses CounterMultiBase as its base counter type.


A percentage counter that shows the active time of one or more components as a percentage of the total time of the sample interval. These counters are known as inverse multitimer counters, as multitimers monitor multiple component instances (like a volume or processor), and inverse counters measure nonactive time and derive active time from that measure. Measures time in system ticks.


Measures active time of one or more components in 100ns increments.


Measures active time of one or more components in 100ns increments by tracking the nonactive time and deriving the active time from that (inverse timer).


Calculates a percentage of the RawFraction counter value over the RawBase counter value. This counter uses RawBase as its base counter type.


Calculates the SampleCounter value change over the corresponding SampleBase value change per second. This counter uses SampleBase as its base counter type.


Calculates the percentage of SampleCounter value change over the SampleBase value change. This counter uses SampleBase as its base counter type.

See Also

See Recipe 8.11; see the "PerformanceCounter Class," "PerformanceCounterType Enumeration," "PerformanceCounterCategory Class," "ASP.NET Impersonation," and "Monitoring Performance Thresholds" topics in the MSDN documentation.

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows