Notes on C# Performance Counters

What’s Going On Here?

I’m currently reading up on Performance Counters in .NET, and have been taking notes on the topic, so I can refer back later.

These are a series of links and facts that I found helped me understand the topic. Most of the information was available on MSDN, so the relevant links are included.

Some Links

Performance counters front page: http://msdn.microsoft.com/en-us/library/w8f5kw2e.aspx

Runtime Profiling: http://msdn.microsoft.com/en-gb/library/w4bz2147(v=vs.110).aspx

Overview

Performance counter can be used for both for reading and writing pre-defined or custom performance counters.

Reading an Existing or Pre-Defined System Counter

To use, simply instantiate an object, set CategoryName, CounterName, and, optionally, InstanceName and MachineName. and then call NextValue().

The following will get us some simple perf stats:

PerformanceCounter PC = new PerformanceCounter();
PC.CategoryName = "Process";
PC.CounterName = "Private Bytes";
PC.InstanceName = "Explorer";
Console.WriteLine(PC.NextValue().ToString());

Creating a Custom Counter.

You might want to create a custom performance counter, for example, you may choose to instrument the number of records returned from a query over time. We could expose this through a performance counter, and monitor it through Perfmon.

To write to a custom performance counter:

  1. Create a new CounterCreationData class. We need:
  2. Create a CounterCreationDataCollection and add the CounterCreationData class to it.
  3. Create a custom PerformanceCounterCategory counter using PerformanceCounterCategory.Create
  4. Create an instance of the PerformanceCounter class.
  5. Make the PerformanceCounter instance writeable by setting the ReadOnly property to false
  6. Assign CategoryName, CounterName. (Optionally we can set InstanceName and MachineName also).
  7. Call, IncrementBy, Increment, Decrement or set RawValue (note, RawValue does not use Interlocked for multithreading)

These bullet points are reflected in the code below:

// 1. Create a new CounterCreationData instance 
CounterCreationData ccd = new CounterCreationData(
    "AAAACounter1", // Counter name
    "AAA Counter Help",  //Counter help text
    PerformanceCounterType.NumberOfItems32); //Counter type

// 2. Create a CounterCreationDataCollection
CounterCreationDataCollection ccds = new CounterCreationDataCollection();
ccds.Add(ccd);

// Code to demonstrate how to delete a category if we need to.
// PerformanceCounterCategory.Delete("AAAA");

// Check to see if our performance counter category if we need to
if (!PerformanceCounterCategory.Exists("AAAA"))
{
    // 3. Create the PerformanceCounterCategory
    PerformanceCounterCategory.Create(
        "AAAA",
        "AAAA Category Help",
        PerformanceCounterCategoryType.SingleInstance,
        ccds);
}

// 4. Create an instance of the PerformanceCounter class
PerformanceCounter PC = new PerformanceCounter();

// 5. Make the counter writable by setting the .ReadOnly property to false
PC.ReadOnly = false;

// 6. Assign the Category name and Counter Name.
PC.CategoryName = "AAAA";
PC.CounterName = "AAAACounter1";

// 7. Set the counter RawValue and increment
PC.RawValue = 0;
for (int x = 0; x < 100000000; x++)
{
    PC.Increment();
    if (x % 100 == 0)
    {
        Console.WriteLine(x);
    }
}

You may get a security exception when you execute the code. This is because the account under which you’re running the code does not have appropriate permissions on you operating system.

In which case, you’ll need to add the following to the application manifest:

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
  <security>
    <requestedPrivileges>
      <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
    </requestedPrivileges>
  </security>
</trustInfo>

This gets you around the problem, but may not be the best approach. For more info, consult: What do if you get a  SecurityException. I’d recommend reading it, as there’s more useful info on this with regard to alternative approaches.

Also note that this ensures the application requests privileges when it is run. This doesn’t help us help us when attempting to debug the application. For that, we need to run Visual Studio as an administrator. When I tried it with VS2012 on Windows 8, the application  prompted me about this, and then upon confirmation restarted automatically.

We can now view the new counter in Perfmon. Note, that all the counter and category information is loaded into Perfmon once when you start it up. To pick up any new or modified counters or counter categories, you’ll need to restart the application if  it’s already open.

Different Sorts of Pre-Defined Performance Counters

Out-of-the box

  • Exception
  • Interop
  • JIT
  • Loading
  • Lock and Thread
  • Memory
  • Networking
  • Security

Performance Counter Types

There are a large number of performance counter types. They are as follows (refer to MSDN for more information)

  • NumberOfItems32/64, NumberOfItemsHEX32/64.
  • RateOfCountsPerSecond32/64
  • CountPerTimeInterval32/64
  • RawFraction
  • RawBase
  • AverageTimer32
  • AverageBase
  • AverageCount64
  • SampleFraction
  • SampleCounter
  • SampleBase
  • CounterTimer
  • CounterTimerInverse
  • Timer100Ns
  • Timer100NsInverse
  • ElapsedTime
  • CounterMultiTimer
  • CounterMultiTimerInverse
  • CounterMultiTimer100Ns
  • CounterMultiTimer100NsInverse
  • CounterMultiBase
  • CounterDelta32/64

In general, we can break these counters down to five specific types:

  1. Average: Measure a value over time and display the average of the last two measurements. Needs a base counter.
  2. Difference: Subtract the last measurement from the previous one and display the difference
  3. Instantaneous: Display the most recent measurement.:
  4. Percentage: Display calculated values as a percentage.
  5. Rate: Change in values ovwer time divided by the time period.

Some counters require a base counter. Base counters must be included immediately after the desired counter in the ConterCreationData structure.

There are four base counter types: AverageBaseCounterMultiBase, RawBase, SampleBase. Timers that require a base timer will start with the same text as those timers. For example: AverageTimer32 will require AverageBase.

Performance Counter Category Types

There are three types: Unknown, Single and Multi.

A counter is a single instance upon first creation. When other instances are created it becomes a multi-instance.

 

Leave a Reply