2010-10-09 12 views
9

Jaka jest najmniejsza ilość kodu C#, aby uruchomić licznik wydajności?Najprostszy możliwy licznik wydajności Przykład

Po prostu chcę zmierzyć liczbę cykli procesora i/lub czas między dwoma punktami w moim kodzie. Przeszukałem wszystkie gofry w Internecie, ale wydaje mi się, że WAY ma więcej kodu, niż jest to konieczne do tak trywialnego zadania. Chcę tylko uruchomić szybki pomiar i skoncentrować się na tym, nad czym pracuję.

Odpowiedz

26

Nie sądzę, że potrzebujesz do tego licznika wydajności. Potrzebujesz więcej niż czasu, który możesz uzyskać od StopWatch? Jest bardzo dokładny.

Stopwatch watch = Stopwatch.StartNew(); 

// Do work 

watch.Stop(); 
// elapsed time is in watch.Elapsed 

Jednak, aby odpowiedzieć na pytanie, które faktycznie zadałeś: Jeśli chcesz tylko zapytać istniejące liczniki, jest to w rzeczywistości bardzo proste. Oto pełny przykład:

using System; 
using System.Diagnostics; 
using System.Linq; 

static class Test 
{ 
    static void Main() 
    { 
     var processorCategory = PerformanceCounterCategory.GetCategories() 
      .FirstOrDefault(cat => cat.CategoryName == "Processor"); 
     var countersInCategory = processorCategory.GetCounters("_Total"); 

     DisplayCounter(countersInCategory.First(cnt => cnt.CounterName == "% Processor Time")); 
    } 

    private static void DisplayCounter(PerformanceCounter performanceCounter) 
    { 
     while (!Console.KeyAvailable) 
     { 
      Console.WriteLine("{0}\t{1} = {2}", 
       performanceCounter.CategoryName, performanceCounter.CounterName, performanceCounter.NextValue()); 
      System.Threading.Thread.Sleep(1000); 
     } 
    } 
} 

Oczywiście proces będzie wymagał odpowiednich uprawnień dostępu do liczników wydajności, których potrzebujesz.

+0

Być może powinienem był opracować, że próbowałem wdrożyć prosty silnik Regex. Czy stoper będzie na tyle dokładny? –

+0

@Paul Matthews - będzie dobrze. Rozdzielczość stopera jest w kleszczach – Oded

+1

Jest wystarczająco dokładna do mierzenia wydajności twojego kodu, jeśli o to pytasz. Pamiętaj, aby uruchamiać kod w trybie Release poza Visual Studio, jeśli mierzysz wydajność. Zaleciłbym również użycie narzędzia do profilowania w celu zmierzenia wydajności, o wiele więcej dowiesz się o wydajności kodu niż prosty pomiar czasu do punktu. – driis

2

Nie ma sposobu, aby uzyskać to i działa w .NET. Jednak najprostszym sposobem, jaki udało mi się znaleźć, jest zbudowanie na bazie biblioteki Enterprise, która zapewnia trochę gotowości do pracy z licznikami wydajności. Na przykład: the Performance Counter Handler

Biblioteka korporacyjna zapewnia również pewne możliwości znacznie łatwiejszego zarządzania instalacją liczników wydajności.

Dodatkowo niech zbudować na nim tak, można utworzyć AvergeTimeMeter który pozwala po prostu to zrobić:

private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounter = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTime); 
private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounterBase = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTimeBase); 

public void DoSomethingWeWantToMonitor() 
{ 
    using (new AverageTimeMeter(averageRequestTimeCounter, averageRequestTimeCounterBase)) 
    { 
     // code here that you want to perf mon 
    } 
} 

Pozwala to po prostu hermetyzacji kodu chcesz monitorować w sposób używając bloku - i skoncentruj się na kodzie, nad którym chcesz pracować, zamiast martwić się o całą infrastrukturę licznika wydajności.

Aby to zrobić, musisz utworzyć wielokrotnego użytku klasę AverageTimeMeter takiego:

public sealed class AverageTimeMeter : IDisposable 
{ 
    private EnterpriseLibraryPerformanceCounter averageCounter; 
    private EnterpriseLibraryPerformanceCounter baseCounter; 
    private Stopwatch stopWatch; 
    private string instanceName; 

    public AverageTimeMeter(EnterpriseLibraryPerformanceCounter averageCounter, EnterpriseLibraryPerformanceCounter baseCounter, string instanceName = null) 
    { 
     this.stopWatch = new Stopwatch(); 
     this.averageCounter = averageCounter; 
     this.baseCounter = baseCounter; 
     this.instanceName = instanceName; 
     this.stopWatch.Start(); 
    } 

    public void Dispose() 
    { 
     this.stopWatch.Stop(); 
     if (this.baseCounter != null) 
     { 
      this.baseCounter.Increment(); 
     } 

     if (this.averageCounter != null) 
     { 
      if (string.IsNullOrEmpty(this.instanceName)) 
      { 
       this.averageCounter.IncrementBy(this.stopWatch.ElapsedTicks); 
      } 
      else 
      { 
       this.averageCounter.SetValueFor(this.instanceName, this.averageCounter.Value + this.stopWatch.ElapsedTicks); 
      } 
     } 
    } 

} 

musisz zarejestrować swoje liczniki wydajności (pokazane na przykładach EntLib), ale powinien dostać swoją zaczęło.

+0

Na podstawie komentarzy, które widzę powyżej, wygląda na to, że prawdopodobnie twoje pytanie było bardziej związane z mierzeniem kodu, a nie aż tak * specjalnie * dla liczników wydajności. Zawsze pytam konkretnie z perspektywy liczników wydajności - jeśli tego nie potrzebujesz, to zgadzam się, że Stoper jest najprostszą drogą. –

+0

Ostatni raz użyłem liczników wydajności w Delphi, więc może terminologia nieco się zmieniła. Przepraszam, jeśli zaprowadziłem cię ścieżką do ogrodu :) –

-1

Możesz ustawić zmienną statyczną nazywaną licznikiem jako długą i utworzyć wątek, który ją zwiększy. Możesz rozpocząć i przerwać ten wątek, kiedy tylko chcesz i/lub potrzebujesz. Gdy wątek jest uruchomiony, możesz użyć liczby całkowitej licznika statycznego, aby zmierzyć liczbę cykli procesora i/lub czas między dwoma punktami w kodzie. Wątek i technikę licznika statycznego można porównać do użycia metod Stop Start Restart Restart i ElapsedTicks.

+1

Brzmi interesująco. Naprawdę nie rozumiem, w jaki sposób użycie innego wątku do pomiaru cykli procesora dałoby nam dokładny pomiar? Czy mamy gwarancję, że wątek zajmuje dokładnie te same fragmenty czasu procesora, co wątek, który mierzymy? –

6

lubię coś, co można wziąć dowolny blok kodu i owinąć go stoper kod profilowania mierzyć czas spędzony na wykonanie go:

using System.Diagnostics; 
    using System.Threading; 

    public static T Profile<T>(Func<T> codeBlock, string description = "") 
    { 
     Stopwatch stopWatch = new Stopwatch(); 
     stopWatch.Start(); 
     T res = codeBlock(); 
     stopWatch.Stop(); 
     TimeSpan ts = stopWatch.Elapsed; 
     const double thresholdSec = 2; 
     double elapsed = ts.TotalSeconds; 
     if(elapsed > thresholdSec) 
      System.Diagnostics.Debug.Write(description + " code was too slow! It took " + 
      elapsed + " second(s)."); 
     return res; 
    } 

Następnie nazwać tak:

Profile(() => MyObj.MySlowMethod()); 

lub:

Profile(() => MyObj.MySlowMethod(), "I can explain why"); 
+0

Bardzo fajnie! –

Powiązane problemy