February 28, 2021
Hot Topics:

Performance Counters Determine Application Performance

  • By Mark Strawmyer
  • Send Email »
  • More Articles »

Use of Performance Counters

Now that you've created the counters, it's time to use them programmatically.

Performance Counter Usage Sample Code

The following sample code demonstrates the programmatic use of performance counters. It contains a helper class to control the counters within a specific category:

using System;using System.Diagnostics;namespace CodeGuru.Instrumentation{   /// <summary>   /// Helper class to demonstrate the setup of performance counters.   /// </summary>   public class PerformanceCounterHelper{   // Total number of tests executed   private PerformanceCounter _TotalTests = null;   // Total tests executed per second   private PerformanceCounter _TestsPerSecond = null;   // Average test duration   private PerformanceCounter _AverageTest = null;   // Average test duration base   private PerformanceCounter _AverageTestBase = null;   /// <summary>   /// Constructor   /// </summary>   public PerformanceCounterHelper()   {   // Set up the performance counter(s)   if( !PerformanceCounterCategory.Exists("CodeGuru Sample") )   {      // Create the collection container      CounterCreationDataCollection counters = new          CounterCreationDataCollection();      // Create counter #1 and add it to the collection      CounterCreationData tests = new CounterCreationData();      tests.CounterName = "Total Tests Executed";      tests.CounterHelp = "Total number of tests executed.";      tests.CounterType = PerformanceCounterType.NumberOfItems32;      counters.Add(tests);      // Create counter #2 and add it to the collection      CounterCreationData testsPerSec = new CounterCreationData();      testsPerSec.CounterName = "Tests Executed / sec";      testsPerSec.CounterHelp = "Number of tests executed per                                 second.";      testsPerSec.CounterType =          PerformanceCounterType.RateOfCountsPerSecond32;      counters.Add(testsPerSec);      // Create counter #3 and add it to the collection      CounterCreationData avgTest = new CounterCreationData();      avgTest.CounterName = "Average Test Duration";      avgTest.CounterHelp = "Average time to execute a test.";      avgTest.CounterType = PerformanceCounterType.AverageTimer32;      counters.Add(avgTest);      // Create counter #4 and add it to the collection      CounterCreationData avgTestBase = new CounterCreationData();      avgTestBase.CounterName = "Average Test Duration Base";      avgTestBase.CounterHelp = "Average time to execute a test                                 base.";      avgTestBase.CounterType = PerformanceCounterType.AverageBase;      counters.Add(avgTestBase);      // Create the category and all of the counters.      PerformanceCounterCategory.Create("CodeGuru Sample",         "Sample performance counters for CodeGuru article.",         counters);      }      _TotalTests              = new PerformanceCounter();      _TotalTests.CategoryName = "CodeGuru Sample";      _TotalTests.CounterName  = "Total Tests Executed";      _TotalTests.MachineName  = ".";      _TotalTests.ReadOnly     = false;      _TestsPerSecond              = new PerformanceCounter();      _TestsPerSecond.CategoryName = "CodeGuru Sample";      _TestsPerSecond.CounterName = "Tests Executed / sec";      _TestsPerSecond.MachineName = ".";      _TestsPerSecond.ReadOnly    = false;      _AverageTest              = new PerformanceCounter();      _AverageTest.CategoryName = "CodeGuru Sample";      _AverageTest.CounterName  = "Average Test Duration";      _AverageTest.MachineName  = ".";      _AverageTest.ReadOnly     = false;      _AverageTestBase              = new PerformanceCounter();      _AverageTestBase.CategoryName = "CodeGuru Sample";      _AverageTestBase.CounterName  = "Average Test Duration Base";      _AverageTestBase.MachineName  = ".";      _AverageTestBase.ReadOnly     = false;      }      /// <summary>      /// Increment the CodeGuru sample counters.      /// </summary>      /// <param name="Ticks">Timing interval</param>      public void IncrementCounters(long Ticks)      {         _TotalTests.Increment();         _TestsPerSecond.Increment();         _AverageTest.IncrementBy(Ticks);         _AverageTestBase.Increment();      }   }}

This code creates a Windows Forms application that features a single button to test the counters. By adding the following code to the _Click event buttons, you enable it to simulate some processing and update the counters along the way:

long startTime = 0;PerformanceCounterHelper counterHelper = new   PerformanceCounterHelper();Random interval = new Random(500);for( int i = 0; i < 300; i++ ){   startTime = DateTime.Now.Ticks;   System.Threading.Thread.Sleep(interval.Next(500));   counterHelper.IncrementCounters(DateTime.Now.Ticks - startTime);}

Performance Counter Output

Figure 3 shows the output of executing the above sample code. The screenshot appears after opening the performance monitor, removing the default counters, and adding in the custom counters.

Figure 3—Screenshot of Performance Counter Output

Note that the sampling interval can influence how your counters behave. If you increment and decrement a counter prior to a sampling occurring, the increment action will have no bearing on the performance output.

Possible Enhancements

You have seen some of the basics of using performance counters, along with examples of the more commonly used types. Now, it is up to you to further explore the rest to the available performance counter types and how they may benefit your applications. You may find it helpful to create helper classes for each of the categories of performance counters you wish to create. This will allow you to centralize the use of performance counters and prevent you from duplicating code at each location where the counters will be utilized.

Future Columns

The topic of the next column is yet to be determined. If you have something in particular that you would like to see explained here, you can reach me at mstrawmyer@crowechizek.com.

About the Author

Mark Strawmyer, MCSD, MCSE, MCDBA is a Senior Architect of .NET applications for large and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C#. You can reach Mark at mstrawmyer@crowechizek.com.

Page 3 of 3

This article was originally published on May 11, 2004

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date