Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#4.0

A Performance Counters Helper Class

4.86/5 (9 votes)
16 Jan 2012CPOL3 min read 36.5K   726  
A performance counters helper class that makes it easier to use performance counters in your system, especially for measuring duration and total duration

Introduction

In the last project I was working on, we needed to add some performance counters to measure the duration of various parts of the system. There is information on performance counters in MSDN and also in CodeProject, but we just could not find the exact information we were looking for.

We started by creating a performance counters manager for one part of our system that specifically handled counting duration of operations. But then, we realized that we required similar functionality in other parts of the system. So we created a base class PerformanceCountersManagerBase as a helper class for writing performance counters.

Using the Code

The attached code shows a simplified usage of the PerformanceCountersManagerBase.

The sample is divided into 3 parts:

  • Core. This contains the implementation of the PerformanceCountersManagerBase.
  • Impl. This contains an implementation of MyPerformanceCountersManager that inherits from PerformanceCountersManagerBase.
  • PerformanceCountersSample. This uses the MyPerformanceCountersManager to measure the duration and total duration of some operations in our sample.

After you install the performance counters as explained below, you can run the sample, open the performance monitor and observe the performance counters as they change over time.

Install New Performance Counters Programmatically

  • Create a performance counters manager that extends PerformanceCountersManagerBase and defines the required performance counters:
C#
 public class MyPerformanceCountersManager : PerformanceCountersManagerBase
{
    /// <summary>
    /// The category of the counters managed by this manager.
    /// </summary>
    public const string CategoryName = "SampleCategory";

    /// <summary>
    /// The name of the counter that measures duration of some operation.
    /// </summary>
    public const string SomeOperationDurationCounterName = "Some Operation Time";

    private static int s_instanceCounter;

    public static bool CountersInstalled
    {
        get { return PerformanceCounterCategory.Exists(CategoryName); }
    }

    public static void InstallCounters()
    {
        if (CountersInstalled) return;

        var counters = new CounterCreationDataCollection
                            {
                                new CounterCreationData
                                    {
                                        CounterName =
                                            SomeOperationDurationCounterName,
                                        CounterHelp =
                                            "Duration in milliseconds it takes to 
                    execute some operation.",
                                        CounterType = 
                    PerformanceCounterType.NumberOfItems64,
                                    },
                            };

        PerformanceCounterCategory.Create(
            CategoryName,
            "Sample counters",
            PerformanceCounterCategoryType.MultiInstance,
            counters);
    }

    public MyPerformanceCountersManager(string instanceName)
    {
        instanceName = string.Format(
            CultureInfo.InvariantCulture,
            "{0}_{1}",
            instanceName,
            s_instanceCounter++);

        PerformanceCounters.Add(
            SomeOperationDurationCounterName,
            CreateWritablePerformanceCounter(CategoryName,
                SomeOperationDurationCounterName,
                instanceName));
    }
}       

This class defines a performance counter called Some Operation Time, under category SomeCategory. The counter is of type NumberOfItems64, which just updates the value each time it is used. For a comprehensive list of possible performance counters, please refer to MSDN.

The static InstallCounters method is used to define the performance counters.

This constructor is used to create instances of the performance counters. This sample uses a per instance performance counter.

  • Create an installer for installing the performance counters. Impl contains MyPerformanceCountersInstaller for doing just that:
C#
[RunInstaller(true)]
public class MyPerformanceCountersInstaller : Installer
{
    public override void Install(IDictionary stateSaver)
    {
        base.Install(stateSaver);
        if (!PerformanceCounterCategory.Exists(MyPerformanceCountersManager.CategoryName))
        {
            MyPerformanceCountersManager.InstallCounters();
        }
    }

    public override void Uninstall(IDictionary savedState)
    {
        base.Uninstall(savedState);
        if (PerformanceCounterCategory.Exists(MyPerformanceCountersManager.CategoryName))
        {
            PerformanceCounterCategory.Delete(MyPerformanceCountersManager.CategoryName);
        }
    }
}

You can install the performance counters by opening a Visual Studio command prompt (as administrator), navigating to the impl\bin\debug directory and executing:

installutil Impl.dll

If everything goes well, you should be able to see the new category with the new performance counter similar to the following:

new performance counters installed

Using Performance Counters that Measure Duration

  • Install a performance counter of type NumberOfItems64 (as defined in the previous section).
  • Make sure you have a relevant instance of a performance counters manager. You can use the NullPerformanceCountersManager. This is an implementation of the Null Object pattern that can save you from verifying for null reference each time you want to use the performance counters manager.
C#
private IPerformanceCountersManager m_performanceCountersManager = 
                new NullPerformanceCountersManager();
private void InitializePerformanceCountersManagerIfNecessary()
{
    if (!MyPerformanceCountersManager.CountersInstalled) return;

    m_performanceCountersManager = new MyPerformanceCountersManager
                    (Guid.NewGuid().ToString());
}
  • Before the operation you want to measure, do the following:
C#
m_performanceCountersManager.StartWatch
    (MyPerformanceCountersManager.SomeOperationDurationCounterName);
  • After the operation you want to measure, do the following:
C#
m_performanceCountersManager.StopWatch
    (MyPerformanceCountersManager.SomeOperationDurationCounterName);

The performance counter is updated after calling the StopWatch with the elapsed milliseconds from the call to StartWatch.

Using Performance Counters that Measure Total Duration

Sometimes, you need to sum the duration of each operation into one performance counter which contains their total.

  • Install a performance counter of type NumberOfItems64 (as defined in the previous section).
  • When you want to start the measuring cycle, call the following:
C#
m_performanceCountersManager.ResetCounterValue(
    MyPerformanceCountersManager.TotalOperationDurationCounterName);
  • Each time you need to update the counter value with the elapsed time of some other counter, you can do the following:
C#
m_performanceCountersManager.IncrementCounterValueBy(
    MyPerformanceCountersManager.TotalOperationDurationCounterName,
    m_performanceCountersManager.GetElapsedMilliseconds(
        MyPerformanceCountersManager.SomeOperationDurationCounterName));

Note that the counter is not actually updated when calling IncrementCounterValueBy. Only the internal value, kept in the performance counter manager, is updated.

  • When you want to actually update the counter (at the end of the measuring cycle), call the following:
C#
m_performanceCountersManager.UpdateCounter
    (MyPerformanceCountersManager.TotalOperationDurationCounterName);

Other Operations with Performance Counters

Performance counters have operations like Increment and IncrementBy. If you need a performance counter (like counters per second), you can update the counter by using something similar to:

C#
m_performanceCountersManager.Increment
    (MyPerformanceCountersManager.OperationsPerSecondCounterName);

History

  • 16th January, 2012: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)