Как использовать счетчики производительности AverageTimer32 и AverageBase с System.Diagnostics.Stopwatch? - PullRequest
23 голосов
/ 10 октября 2009

Когда я выполняю следующую программу и смотрю на счетчик производительности, результаты для меня не имеют смысла. Среднее значение равно нулю, а минимальное / максимальное значения составляют ~ 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

Ответы [ 3 ]

33 голосов
/ 10 октября 2009

API System.Diagnostics содержит довольно тонкий источник путаницы: «галочки» System.Diagnostics не совпадают с «галочками» DateTime или TimeSpan!

Если вы используете StopWatch.ElapsedTicks вместо StopWatch.Elapsed.Ticks, оно должно работать.

Документация содержит дополнительную информацию об этом.

9 голосов
/ 10 февраля 2012

Марк Симанн объяснил запутанный источник проблемы, но я хотел бы предоставить немного дополнительной информации.

Если вы хотите установить AverageTimer32 счетчик производительности для TimeSpan, а не Stopwatch, вы можете выполнить следующее преобразование:

var performanceCounterTicks = timeSpan.Ticks*Stopwatch.Frequency/TimeSpan.TicksPerSecond;
averageTimerCounter.IncrementBy(performanceCounterTicks);
averageTimerCounterBase.Increment();
0 голосов
/ 11 июня 2014

Это старая ветка, но я подумал, что должен вмешаться. Кто-то из Microsoft сказал мне, что не следует использовать 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...