Click here to Skip to main content
15,860,943 members
Articles / Programming Languages / C# 4.0
Article

A Performance Counters Helper Class

Rate me:
Please Sign up or sign in to vote.
4.86/5 (9 votes)
16 Jan 2012CPOL3 min read 35.6K   726   36   10
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)


Written By
Software Developer (Senior)
Israel Israel
Ron is focused on .net and C# development since 2003.
In his various roles Ron was part of the whole release cycle starting from the initial requirements to release. Ron participated in Agile projects using Scrum and in projects managed with the waterfall methodology.
Ron worked as a developer, developer lead and as a test owner in a variety of technologies - languages like C# & Java, databases like MSSQL and more.
Ron always seeks for new opportunities to learn something new - whether a better development methodology, a design pattern or architecture to build better software.
Ron enjoys mentoring others on effective application development using SOLID design and architecture principles, test driven development and unit testing.

Comments and Discussions

 
QuestionHow to install in a machine where no Visual Studio is available Pin
Member 113655914-Oct-16 11:27
Member 113655914-Oct-16 11:27 
Questionany wrong ? Pin
Harly14-May-15 23:50
Harly14-May-15 23:50 
Questionany wrong ?? Pin
Harly14-May-15 23:36
Harly14-May-15 23:36 
GeneralMy vote of 5 Pin
Joezer BH25-Nov-13 21:28
professionalJoezer BH25-Nov-13 21:28 
GeneralMy vote of 5 Pin
SearcherM18-Dec-12 2:46
SearcherM18-Dec-12 2:46 
GeneralRe: My vote of 5 Pin
Ron Sher18-Dec-12 4:02
Ron Sher18-Dec-12 4:02 
QuestionMessage Closed Pin
16-Aug-12 18:46
kianurieves16-Aug-12 18:46 
AnswerRe: nice article Pin
Ron Sher16-Aug-12 20:52
Ron Sher16-Aug-12 20:52 
GeneralMy vote of 5 Pin
Kanasz Robert18-Jan-12 22:01
professionalKanasz Robert18-Jan-12 22:01 
GeneralRe: My vote of 5 Pin
Ron Sher25-Jan-12 18:13
Ron Sher25-Jan-12 18:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.