c# .net performancecounter

c# - ¿Cómo utilizar los contadores de rendimiento AverageTimer32 y AverageBase con System.Diagnostics.Stopwatch?



.net performancecounter (3)

Cuando ejecuto el siguiente programa y miro el contador de rendimiento, los resultados no tienen sentido para mí. El valor promedio es cero y los valores mínimos / máximos son ~ 0.4 cuando esperaría ~ 0.1 o ~ 100.

Cual es mi problema

Código

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

Captura de pantalla del contador de rendimiento Captura de pantalla del contador de rendimiento http://friendfeed-media.com/50028bb6a0016931a3af5122774b56f93741bb5c


Este es un tema antiguo, pero pensé que podría intervenir. Alguien de Microsoft me dijo que no debería usar TimeSpan , StopWatch o DateTime cuando trabaje con los Contadores de rendimiento. En su lugar, recomendó agregar el siguiente método nativo a mi proyecto:

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

Al incrementar un contador, recomendó hacerlo así:

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


La API System.Diagnostics contiene una fuente bastante sutil de gran confusión: las "marcas" de System.Diagnostics no son lo mismo que las "marcas" de DateTime o TimeSpan.

Si usa StopWatch.ElapsedTicks lugar de StopWatch.Elapsed.Ticks, debería funcionar.

La StopWatch.ElapsedTicks contiene más información sobre esto.


Mark Seemann explicó la fuente confusa del problema, pero me gustaría proporcionar un poco de información adicional.

Si desea configurar su AverageTimer32 rendimiento AverageTimer32 desde un TimeSpan y no desde un Stopwatch , puede realizar la siguiente conversión:

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