2010-10-09 7 views
9

Qual è la quantità minima di codice C# per ottenere un contatore delle prestazioni attivo e funzionante?Esempio di contatore delle prestazioni più semplice

Voglio semplicemente misurare il numero di cicli della CPU e/o il tempo tra due punti nel mio codice. Ho sfogliato tutti i waffle sul web ma sembra che WAY abbia più codice di quanto sia necessario per un compito così banale. Voglio solo ottenere una misurazione rapida e funzionante e concentrarmi maggiormente su ciò su cui sto lavorando.

risposta

26

Non penso che sia necessario un contatore delle prestazioni. Hai bisogno di più del tempo che puoi ottenere da StopWatch? È molto accurato

Stopwatch watch = Stopwatch.StartNew(); 

// Do work 

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

Tuttavia, per rispondere alla domanda che realmente chiesto: Se si desidera solo per interrogare i contatori esistenti, è in realtà abbastanza semplice. Ecco un esempio completo:

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

Naturalmente, il processo avrà bisogno di autorizzazioni appropiate per accedere ai contatori delle prestazioni necessarie.

+0

Forse avrei dovuto elaborato che stavo cercando di implementare un semplice motore di Regex. Il cronometro sarà abbastanza preciso per quello? –

+0

@Paul Matthews - andrà bene. La risoluzione del cronometro è espressa in tick – Oded

+1

È sufficientemente accurata per misurare le prestazioni del tuo codice, se è quello che stai chiedendo. Ricorda di eseguire il codice in modalità di rilascio all'esterno di Visual Studio se stai misurando le prestazioni. Inoltre, ti consiglio di utilizzare un profiler per misurare le prestazioni, ti dirà molto di più sulle prestazioni del tuo codice rispetto a una semplice misurazione del tempo da punto a punto. – driis

2

Non c'è il banale modo per ottenere questo in esecuzione. NET. Tuttavia, il modo più semplice che ho trovato è quello di costruire sulla Enterprise Library che fornisce alcune funzionalità pronte all'uso per lavorare con i contatori delle prestazioni. Ad esempio: the Performance Counter Handler

La libreria Enterprise offre anche alcune funzionalità per una gestione molto più semplice dell'installazione di contatori delle prestazioni.

Inoltre, ti permette di costruire su di esso in modo, è possibile creare un AvergeTimeMeter che permette di fare solo questo:

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 
    } 
} 

Questo permette di incapsulare semplicemente il codice che si desidera monitorare in un usando il blocco - e concentrati sul codice su cui vuoi lavorare piuttosto che preoccuparti di tutta l'infrastruttura del contatore delle prestazioni.

Per fare questo, si creerà una classe riutilizzabile AverageTimeMeter come questo:

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

} 

Devi registrare i contatori delle prestazioni (mostrati negli esempi EntLib), ma questo dovrebbe ottenere il vostro iniziato.

+0

Sulla base dei commenti che sto vedendo sopra, sembra che la tua domanda fosse più legata alla misurazione del codice e non tanto * specificamente * per i contatori delle prestazioni. Ho sempre una domanda specifica dal punto di vista dei contatori di prestazioni: se non ne hai bisogno, sono d'accordo che Stopwatch è il modo più semplice per andare. –

+0

L'ultima volta che ho usato i contatori delle prestazioni era in Delphi, quindi forse la terminologia è leggermente cambiata. Scusa se ti ho guidato lungo il sentiero del giardino :) –

-1

È possibile rendere variabile statica chiamata contatore quanto lungo e creare un thread che lo incrementa. Puoi iniziare e interrompere questo thread ogni volta che vuoi e/o hai bisogno. Mentre il thread è in esecuzione, è possibile utilizzare il valore intero del contatore statico per misurare il numero di cicli della CPU e/o il tempo tra due punti nel codice. Il Thread e la tecnica del counter statico possono essere confrontati con l'uso dei metodi Stopwatch Start Stop Restart Reset e della proprietà ElapsedTicks.

+1

Sembra un approccio interessante. Non capisco davvero come usare un altro thread per misurare i cicli della CPU ci darebbe una misurazione accurata però? Siamo sicuri che quel thread occupa esattamente le stesse fette di tempo della CPU del thread che stiamo misurando? –

6

mi piace qualcosa che può prendere qualsiasi blocco di codice e avvolgerla con il codice di profiling cronometro per misurare il tempo trascorso eseguendolo:

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

Quindi chiamare in quel modo:

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

o:

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

Davvero fantastico! –