开发者

How to use AverageTimer32 and AverageBase performance counters with System.Diagnostics.Stopwatch?

When I execute the following program and look at the performance counter the results don't make sense to me. The average value is zero and the min/max values are ~0.4 when I would expect ~0.1 or ~100.

What is my problem?

Code

class Program
{
    const string CategoryName = "____Test Category";
    const string CounterName = "Average Operation Time";
    const string BaseCounterName = "Average Operation Time Base";

    static void Main(string[] args)
    {
        if (PerformanceCounterCategory.Exists(CategoryName))
            PerformanceCounterCategory.Delete(CategoryName);

        var counterDataCollection = new CounterCreationDataCollection();

        var avgOpTimeCounter = new CounterCreationData()
        {
            CounterName = CounterName,
            CounterHelp = "Average Operation Time Help",
            CounterType = PerformanceCounterType.AverageTimer32
        };
        counterDataCollection.Add(avgOpTimeCounter);

        var avgOpTimeBaseCounter = new CounterCreationData()
        {
            CounterName = BaseCounterName,
            CounterHelp = "Average Operation Time Base Help",
            CounterType = PerformanceCounterType.AverageBase
        };
        counterDataCollection.Add(avgOpTimeBaseCounter);

        PerformanceCounterCategory.Create(CategoryName, "Test Perf Counters", PerformanceCounterCategoryType.SingleInstance, counterDataCollection);

        var counter = new PerformanceCounter(CategoryName, CounterName, false);
        var baseCounter = new PerformanceCounter(CategoryName, BaseCounterName, false);

        for (int i = 0; i < 500; i++)
        {
            var sw = Stopwatch.StartNew();
            Thread.Sleep(100);
            sw.Stop();

            Console.WriteLine(string.Format("t({0}) ms({1})", sw.Elapsed.Ticks, sw.Elapsed.TotalMilliseconds));
            counter.IncrementBy(sw.Elapsed.Ticks);
            baseCounter.Increment();
        }

        Console.Read();
    }
}

Performance Counter Screenshot Performance Counter Screenshot http://friendfeed-media.com/50028bb6a0016931a3af5开发者_开发知识库122774b56f93741bb5c


The System.Diagnostics API contains a pretty subtle source of great confusion: System.Diagnostics 'ticks' are not the same as DateTime or TimeSpan 'ticks'!

If you use StopWatch.ElapsedTicks instead of StopWatch.Elapsed.Ticks, it should work.

The documentation contains more information about this.


Mark Seemann explained the confusing source of the problem but I would like to provide a little bit of additional information.

If you want to set your AverageTimer32 performance counter from a TimeSpan and not a Stopwatch you can perform the following conversion:

var performanceCounterTicks = timeSpan.Ticks*Stopwatch.Frequency/TimeSpan.TicksPerSecond;
averageTimerCounter.IncrementBy(performanceCounterTicks);
averageTimerCounterBase.Increment();


This is an old thread, but I thought I'd chime in. I was told by someone from Microsoft that I shouldn't use TimeSpan, StopWatch, or DateTime when working with Performance Counters. Instead, he recommended adding the following native method to my project:

internal static class NativeMethods
{
    [DllImport("Kernel32.dll")]
    public static extern void QueryPerformanceCounter(ref long ticks); 
}

When incrementing a counter, he recommended doing so like this:

public void Foo()
{
    var beginTicks = 0L;

    var endTicks = 0L;

    NativeMethods.QueryPerformanceCounter(ref beginTicks);

    // Do stuff

    NativeMethods.QueryPerformanceCounter(ref endTicks);

    this.Counter.IncrementBy(endTicks - beginTicks);
    this.BaseCounter.Increment();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜