Click here to Skip to main content
15,892,298 members
Articles / Programming Languages / C#

An Introduction To Performance Counters

Rate me:
Please Sign up or sign in to vote.
4.74/5 (105 votes)
21 Feb 200510 min read 831K   10.2K   240  
An introduction to monitoring performance of applications.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace PerformanceCounterSample
{
	/// <summary>
	/// Entry class for the sample
	/// </summary>
	class PerformanceCounterSampleStarter
	{
		/// <summary>
		/// Imports the <code>QueryPerformanceFrequency</code> method into the class. The method is used to measure the current
		/// tickcount of the system.
		/// </summary>
		/// <param name="ticks">current tick count</param>
		[DllImport("Kernel32.dll")]
		public static extern void QueryPerformanceCounter(ref long ticks);

		/// <summary>
		/// Main thread
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			PerformanceCounterSample test = new PerformanceCounterSample();
			Random rand = new Random();
			long startTime = 0;
			long endTime = 0;
			
			for (int i=0; i<1000; i++)
			{
				// measure starting time
				QueryPerformanceCounter(ref startTime);

				System.Threading.Thread.Sleep(rand.Next(500));

				// measure ending time
				QueryPerformanceCounter(ref endTime);

				// do some processing
				test.DoSomeProcessing(endTime - startTime);
			}
		}


	}

	/// <summary>
	/// The PerformanceCounterSample class sets up a performance counter category called "MyCategory" if it does not already
	/// exists and adds some counters to it. It provides a method to increment these counters.
	/// </summary>
	public class PerformanceCounterSample
	{
		/// <summary>
		/// Counter for counting total number of operations
		/// </summary>
		private PerformanceCounter _TotalOperations;
		/// <summary>
		/// Counter for counting number of operations per second
		/// </summary>
		private PerformanceCounter _OperationsPerSecond;
		/// <summary>
		/// Counter for counting duration averages
		/// </summary>
		private PerformanceCounter _AverageDuration;
		/// <summary>
		/// Counter for counting duration averages base
		/// </summary>
		private PerformanceCounter _AverageDurationBase;

		/// <summary>
		/// Creates a new performance counter category "MyCategory" if it does not already exists and adds some counters to it.
		/// </summary>
		public PerformanceCounterSample()
		{
			if (!PerformanceCounterCategory.Exists("MyCategory"))
			{
				CounterCreationDataCollection counters = new CounterCreationDataCollection();

				// 1. counter for counting totals: PerformanceCounterType.NumberOfItems32
				CounterCreationData totalOps = new CounterCreationData();
				totalOps.CounterName = "# operations executed";
				totalOps.CounterHelp = "Total number of operations executed";
				totalOps.CounterType = PerformanceCounterType.NumberOfItems32;
				counters.Add(totalOps);

				// 2. counter for counting operations per second: PerformanceCounterType.RateOfCountsPerSecond32
				CounterCreationData opsPerSecond = new CounterCreationData();
				opsPerSecond.CounterName = "# operations / sec";
				opsPerSecond.CounterHelp = "Number of operations executed per second";
				opsPerSecond.CounterType = PerformanceCounterType.RateOfCountsPerSecond32;
				counters.Add(opsPerSecond);

				// 3. counter for counting average time per operation: PerformanceCounterType.AverageTimer32
				CounterCreationData avgDuration = new CounterCreationData();
				avgDuration.CounterName = "average time per operation";
				avgDuration.CounterHelp = "Average duration per operation execution";
				avgDuration.CounterType = PerformanceCounterType.AverageTimer32;
				counters.Add(avgDuration);

				// 4. base counter for counting average time per operation: PerformanceCounterType.AverageBase
				CounterCreationData avgDurationBase = new CounterCreationData();
				avgDurationBase.CounterName = "average time per operation base";
				avgDurationBase.CounterHelp = "Average duration per operation execution base";
				avgDurationBase.CounterType = PerformanceCounterType.AverageBase;
				counters.Add(avgDurationBase);


				// create new category with the counters above
				PerformanceCounterCategory.Create("MyCategory", "Sample category for Codeproject", counters);
			}

			// create counters to work with
			_TotalOperations = new PerformanceCounter();
			_TotalOperations.CategoryName = "MyCategory";
			_TotalOperations.CounterName = "# operations executed";
			_TotalOperations.MachineName = ".";
			_TotalOperations.ReadOnly = false;
			_TotalOperations.RawValue = 0;

			_OperationsPerSecond = new PerformanceCounter();
			_OperationsPerSecond.CategoryName = "MyCategory";
			_OperationsPerSecond.CounterName = "# operations / sec";
			_OperationsPerSecond.MachineName = ".";
			_OperationsPerSecond.ReadOnly = false;
			_OperationsPerSecond.RawValue = 0;

			_AverageDuration = new PerformanceCounter();
			_AverageDuration.CategoryName = "MyCategory";
			_AverageDuration.CounterName = "average time per operation";
			_AverageDuration.MachineName = ".";
			_AverageDuration.ReadOnly = false;
			_AverageDuration.RawValue = 0;

			_AverageDurationBase = new PerformanceCounter();
			_AverageDurationBase.CategoryName = "MyCategory";
			_AverageDurationBase.CounterName = "average time per operation base";
			_AverageDurationBase.MachineName = ".";
			_AverageDurationBase.ReadOnly = false;
			_AverageDurationBase.RawValue = 0;
		}

		/// <summary>
		/// Increments counters.
		/// </summary>
		/// <param name="ticks">The number of ticks the AverageTimer32 counter must be incremented by</param>
		public void DoSomeProcessing(long ticks)
		{
			// simply increment the counters
			_TotalOperations.Increment();
			_OperationsPerSecond.Increment();
			_AverageDuration.IncrementBy(ticks); // increment the timer by the time cost of the operation
			_AverageDurationBase.Increment(); // increment base counter only by 1
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer Groeger Consulting
Germany Germany
Michael Groeger started .NET early 2001 when it was revealed at the Technical Summit in Neuss, Germany. Before that he was developing mostly using Visual C++ 6 on Windows Platforms or with vi/gc++ on several Unix derivates.

Since 2004 Michael Groeger settled off as freelancer and is focused on projects in the financial and insurance sector.

Comments and Discussions