views:

52

answers:

2

What is the smallest amount of C# code to get a performance counter up and running?

I simply want to measure the number of CPU cycles and/or time between two points in my code. I've skimmed through all the waffle on the web but it seems like WAY more code than is necessary for such a trivial task. I just want to get a quick measurement up and running and concentrate more on what I'm working on.

+2  A: 

I don't think you need a performance counter for that. Do you need more than the timing you can get from StopWatch ? It is very accurate.

Stopwatch watch = Stopwatch.StartNew();

// Do work

watch.Stop();
// elapsed time is in watch.Elapsed

However, to answer the question you actually asked: If you just want to query existing counters, it is in fact quite simple. Here is a full example:

using System;
using System.Diagnostics;
using System.Linq;

static class Test
{
    static void Main()
    {
        var processorCategory = PerformanceCounterCategory.GetCategories()
            .FirstOrDefault(cat => cat.CategoryName == "Processor");
        var countersInCategory = processorCategory.GetCounters("_Total");

        DisplayCounter(countersInCategory.First(cnt => cnt.CounterName == "% Processor Time"));
    }

    private static void DisplayCounter(PerformanceCounter performanceCounter)
    {
        while (!Console.KeyAvailable)
        {
            Console.WriteLine("{0}\t{1} = {2}",
                performanceCounter.CategoryName, performanceCounter.CounterName, performanceCounter.NextValue());
            System.Threading.Thread.Sleep(1000);
        }
    }
}

Of course, the process will need appropiate permissions to access the performance counters you need.

driis
Perhaps I should have elaborated that I was trying to implement a simple Regex engine. Will the stop watch be accurate enough for that?
Paul Matthews
@Paul Matthews - it will fine. The stopwatch resolution is in ticks
Oded
It is accurate enough for measuring performance of your code, if that's what you are asking. Remember to run code in Release mode outside Visual Studio if you are measuring performance. Also, I would recommend you use a profiler to measure performance, it will tell you a lot more about your code's performance than just a simple point-to-point time measurement.
driis
Awesome. Thanks!
Paul Matthews
A: 

There is no trivial way to get this up and running in .NET. However, the simplest way I've found is to build on top of the Enterprise Library which provides some out of the box capabilities for working with performance counters. For example: the Performance Counter Handler

The Enterprise Library also gives you some capabilities for much more easily managing the installation of performance counters.

Additionally, it let's you build on top of it so, you can create an AvergeTimeMeter which allows you to just do this:

private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounter = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTime);
private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounterBase = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTimeBase);

public void DoSomethingWeWantToMonitor()
{
    using (new AverageTimeMeter(averageRequestTimeCounter, averageRequestTimeCounterBase))
    {
        // code here that you want to perf mon
    }
}

This allows you to simply encapsulate the code you want to monitor in a using block - and concentrate on the code you actually want to work on rather than worrying about all the performance counter infrastructure.

To do this, you'll create a re-usable AverageTimeMeter class like this:

public sealed class AverageTimeMeter : IDisposable
{
    private EnterpriseLibraryPerformanceCounter averageCounter;
    private EnterpriseLibraryPerformanceCounter baseCounter;
    private Stopwatch stopWatch;
    private string instanceName;

    public AverageTimeMeter(EnterpriseLibraryPerformanceCounter averageCounter, EnterpriseLibraryPerformanceCounter baseCounter, string instanceName = null)
    {
        this.stopWatch = new Stopwatch();
        this.averageCounter = averageCounter;
        this.baseCounter = baseCounter;
        this.instanceName = instanceName;
        this.stopWatch.Start();
    }

    public void Dispose()
    {
        this.stopWatch.Stop();
        if (this.baseCounter != null)
        {
            this.baseCounter.Increment();
        }

        if (this.averageCounter != null)
        {
            if (string.IsNullOrEmpty(this.instanceName))
            {
                this.averageCounter.IncrementBy(this.stopWatch.ElapsedTicks);
            }
            else
            {
                this.averageCounter.SetValueFor(this.instanceName, this.averageCounter.Value + this.stopWatch.ElapsedTicks);
            }
        }
    }

}

You have to register your performance counters (shown in the EntLib examples) but this should get your started.

Steve Michelotti
Based on the comments I'm now seeing above, it looks like perhaps your question was more related to measuring code and not so much *specifically* for performance counters. I always the question specifically from the perspective of performance counters - if you don't need this, this I agree Stopwatch is the simplest way to go.
Steve Michelotti
The last time I used performance counters was in Delphi so maybe the terminology has changed a little. Sorry if I led you up the garden path :)
Paul Matthews