24

当我执行以下程序并查看性能计数器时,结果对我来说没有意义。平均值为零,最小值/最大值为 ~0.4,而我预计 ~0.1 或 ~100。

我的问题是什么?

代码

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();
    }
}

性能计数器屏幕截图 性能计数器屏幕截图 http://friendfeed-media.com/50028bb6a0016931a3af5122774b56f93741bb5c

4

3 回答 3

34

System.Diagnostics API 包含一个非常微妙的混淆来源:System.Diagnostics 'ticks' 与 DateTime 或 TimeSpan 'ticks' 不同!

如果您使用StopWatch.ElapsedTicks而不是 StopWatch.Elapsed.Ticks,它应该可以工作。

文档包含有关此的更多信息。

于 2009-10-10T06:37:42.010 回答
9

Mark Seemann 解释了问题的令人困惑的根源,但我想提供一些额外的信息。

如果要从 a而不是 a设置AverageTimer32性能计数器,可以执行以下转换:TimeSpanStopwatch

var performanceCounterTicks = timeSpan.Ticks*Stopwatch.Frequency/TimeSpan.TicksPerSecond;
averageTimerCounter.IncrementBy(performanceCounterTicks);
averageTimerCounterBase.Increment();
于 2012-02-10T15:00:04.503 回答
1

这是一个旧线程,但我想我会插话。微软的某个人告诉我,我不应该使用TimeSpan, StopWatch,或者DateTime在使用性能计数器时。相反,他建议将以下本机方法添加到我的项目中:

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

在增加计数器时,他建议这样做:

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();
}
于 2014-06-11T16:50:27.270 回答