2009-10-10 13 views
22

Aşağıdaki programı çalıştırdığımda ve performans sayacına baktığımda, sonuçlar bana mantıklı gelmiyor. Ortalama değer sıfırdır ve min/max değerleri ~ 0,1 veya ~ 100 beklediğimde ~ 0.4'tür.System.Diagnostics.Stopwatch ile AverageTimer32 ve AverageBase performans sayaçlarını nasıl kullanılır?

Sorunum nedir?

Kod

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

Performans Sayacı Ekran Performance Counter Screenshot http://friendfeed-media.com/50028bb6a0016931a3af5122774b56f93741bb5c

cevap

33

System.Diagnostics API büyük bir karışıklık oldukça ince kaynağını içerir: system.diagnostics 'kene' değil aynıdır DateTime veya TimeSpan 'keneler'!

Eğer StopWatch.Elapsed.Ticks yerine StopWatch.ElapsedTicks kullanırsanız, çalışması gerekir.

documentation bu konuda daha fazla bilgi içerir.

9

Mark Seemann, sorunun kafa karıştırıcı kaynağını açıkladı ancak biraz ek bilgi sağlamak istiyorum.

Bir TimeSpan değil aşağıdaki dönüşüm gerçekleştirebilen bir Stopwatch adresinin AverageTimer32 performans sayacı ayarlamak istiyorsanız.

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

işaretlenmemiş ((Int32 döküm gerek Neden ..: Bir sayıcı zaman

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

, o böyle bunu yaparken tavsiye .)? performanceCounterTicks uzun olarak değerlendirilir, tüm değerler aslında uzun sayılardır. –

+0

@DavideIcardi: Teşekkürler, 'IncrementBy' yönteminin imzasının bir "Int64" kabul ettiğini, dolayısıyla bir cast yapmaya gerek olmadığını doğru söylüyorsunuz. Oyuncuyu koddan kaldırdım. –

+0

Güzel! tam aradığım şey! – vtortola

0

Bu eski bir iplik, ama ben uymak düşündüm ben Performans Sayaçları ile çalışırken, Microsoft'tan bir kişi tarafından TimeSpan, StopWatch veya DateTime kullanmamam gerektiği söylendi. Bunun yerine, o benim projeye aşağıdaki yerli yöntemi ekleme önerilenler)

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

Bunun için bir neden de verdi mi? 'StopWatch'' 'QueryPerformanceCounter' üzerinde bir sarıcıdır (mevcut değilse geri dönüş ile). 'StopWatch.IsHighResolution' true ise, 'StopWatch.GetTimeStamp()' 'QueryPerformanceCounter' ile eşdeğerdir. – CodesInChaos

+0

Performansla ilgili bir Microsoft Kalıpları ve Uygulamaları kitabından alıntı yaptı. Onun akıl yürütmesi, aynı eylemi birçok kez gerçekleştirirken olabildiğince az yük olmasını istedim. Performans Sayaçları saniyede birçok kez artırılabilir. Bir StopWatch kullanarak, bir yöntemin performansını ölçmek ve sayacı arttırmak istediğiniz her defasında bir StopWatch nesnesini başlatırsınız. Bu Kronometre nesnelerinin daha sonra çöp toplanması gerekir. "QueryPerformanceCounter" öğesini doğrudan çağırarak ortadaki adamı kesip, Kronometre nesnesinin yapımını ve koleksiyonunu kurtardınız. – RobV8R

+3

'StopWatch.GetTimeStamp()', 'QueryPerformanceCounter' üzerinde statik bir yöntem ve ince bir sarıcıdır.Tek ek maliyet, zaman içinde değişmeyen statik bir alandaki bir daldır, bu yüzden dal tahmini oldukça iyi çalışmalıdır. – CodesInChaos

İlgili konular