2010-02-10 16 views
13

Ho un servizio Windows che serve messaggi di qualche coda virtuale tramite un'interfaccia di servizio WCF. Volevo esporre due contatori di prestazioni -Contatore di tipo RateOfCountsPerSecond32 mostra sempre 0

  1. Il numero di elementi sulla coda
  2. Il numero di elementi rimossi dalla coda al secondo

Il primo funziona bene, il secondo sempre visualizzato come 0 in PerfMon.exe, nonostante RawValue appaia corretto.

Sto creando i contatori in quanto tali -

internal const string PERF_COUNTERS_CATEGORY = "HRG.Test.GDSSimulator"; 
    internal const string PERF_COUNTER_ITEMSINQUEUE_COUNTER = "# Messages on queue"; 
    internal const string PERF_COUNTER_PNR_PER_SECOND_COUNTER = "# Messages read/sec"; 

if (!PerformanceCounterCategory.Exists(PERF_COUNTERS_CATEGORY)) 
{ 
    System.Diagnostics.Trace.WriteLine("Creating performance counter category: " + PERF_COUNTERS_CATEGORY); 
    CounterCreationDataCollection counters = new CounterCreationDataCollection(); 

    CounterCreationData numberOfMessagesCounter = new CounterCreationData(); 
    numberOfMessagesCounter.CounterHelp = "This counter provides the number of messages exist in each simulated queue"; 
    numberOfMessagesCounter.CounterName = PERF_COUNTER_ITEMSINQUEUE_COUNTER; 
    numberOfMessagesCounter.CounterType = PerformanceCounterType.NumberOfItems32; 
    counters.Add(numberOfMessagesCounter); 

    CounterCreationData messagesPerSecondCounter= new CounterCreationData(); 
    messagesPerSecondCounter.CounterHelp = "This counter provides the number of messages read from the queue per second"; 
    messagesPerSecondCounter.CounterName = PERF_COUNTER_PNR_PER_SECOND_COUNTER; 
    messagesPerSecondCounter.CounterType = PerformanceCounterType.RateOfCountsPerSecond32; 
    counters.Add(messagesPerSecondCounter); 

    PerformanceCounterCategory.Create(PERF_COUNTERS_CATEGORY, "HRG Queue Simulator performance counters", PerformanceCounterCategoryType.MultiInstance,counters); 
} 

Poi, per ogni chiamata di servizio, ho incrementare il contatore in questione, per il contatore per ogni/sec questo momento sembra che questo -

messagesPerSecCounter = new PerformanceCounter(); 
messagesPerSecCounter.CategoryName = QueueSimulator.PERF_COUNTERS_CATEGORY; 
messagesPerSecCounter.CounterName = QueueSimulator.PERF_COUNTER_PNR_PER_SECOND_COUNTER; 
messagesPerSecCounter.MachineName = "."; 
messagesPerSecCounter.InstanceName = this.ToString().ToLower(); 
messagesPerSecCounter.ReadOnly = false; 

messagesPerSecCounter.Increment(); 

Come accennato - se inserisco un breakpoint dopo la chiamata per incrementare posso vedere il RawValue in costante aumento, in coerenza con le chiamate al servizio (abbastanza frequentemente, più di una volta al secondo, penserei) Ma il contatore delle prestazioni stesso rimane su 0.

Il contatore delle prestazioni che fornisce il conteggio degli elementi nella "coda", che viene implementato nello stesso modo (sebbene io assegni RawValue, piuttosto che chiamare Incremento) funziona bene.

Cosa mi manca?

+0

Stai davvero la creazione di un nuovo * * contatore ogni volta che incrementarlo? Non è corretto, basta crearne uno. –

+0

Quindi - inizialmente non l'ho fatto e ancora non ha funzionato, ma non penso che sia un problema in quanto tale. Infatti, ho provato un esempio dal web (http://www.codeguru.com/columns/dotnet/article.php/c7279/) che funziona abbastanza bene e ho cambiato il modo di ricreare il contatore delle prestazioni ogni tempo e funziona ancora (anche se sono completamente d'accordo, non è il modo più efficiente. In entrambi i casi - come ho già detto, ho provato entrambi, questo è solo lo stato del codice al momento, mentre continuo a provare varie cose: –

risposta

15

Inizialmente ho avuto anche problemi con questo contatore. MSDN ha un esempio completo di lavoro che mi ha aiutato molto:

http://msdn.microsoft.com/en-us/library/4bcx21aa.aspx

Come il loro esempio è stato abbastanza lungo senza fiato, ho bollito giù ad un singolo metodo per dimostrare lo stretto necessario. Durante l'esecuzione, vedo il valore atteso di 10 conteggi al secondo in PerfMon.

public static void Test() 
{ 
    var ccdc = new CounterCreationDataCollection(); 

    // add the counter 
    const string counterName = "RateOfCountsPerSecond64Sample"; 
    var rateOfCounts64 = new CounterCreationData 
    { 
     CounterType = PerformanceCounterType.RateOfCountsPerSecond64, 
     CounterName = counterName 
    }; 
    ccdc.Add(rateOfCounts64); 

    // ensure category exists 
    const string categoryName = "RateOfCountsPerSecond64SampleCategory"; 
    if (PerformanceCounterCategory.Exists(categoryName)) 
    { 
     PerformanceCounterCategory.Delete(categoryName); 
    } 
    PerformanceCounterCategory.Create(categoryName, "", 
     PerformanceCounterCategoryType.SingleInstance, ccdc); 

    // create the counter 
    var pc = new PerformanceCounter(categoryName, counterName, false); 

    // send some sample data - roughly ten counts per second 
    while (true) 
    { 
     pc.IncrementBy(10); 
     System.Threading.Thread.Sleep(1000); 
    } 
} 

Spero che questo aiuti qualcuno.

+1

Grazie Mikey, è passato un po 'di tempo e mi sono trasferito, quindi non posso convalidarlo sul mio codice originale, ma sembra tutto a posto, ed è molto utile quindi penso che meriti il ​​segno di risposta! –

+0

@ Mike-Chamberlain, ho un problema simile. Un contatore di NumberOfItems64, anche se impostato su un valore (una volta al minuto) viene mostrato in PerfMon come 0. Nel debugger vedo RawValue incrementato. Se faccio semplicemente clic su qualcosa nel debugger, RawValue diventa immediatamente 0. L'impostazione del perf.counter viene eseguita in un'applicazione ASP.NET. Non riesco a ripeterlo a casa in un'applicazione Console. La mia domanda per voi: avete indovinato quale potrebbe essere la ragione per questo, e conoscete qualche soluzione/soluzione alternativa? –

+0

Forse l'app ASP.NET non ha le autorizzazioni per impostare o creare i contatori perf. È possibile provare a eseguire l'app con diritti di amministratore (solo a scopo di test - modificare l'utente per il pool di app in Gestione IIS). In realtà non so quali permessi sono necessari per creare o modificare i contatori perf. – Palo

0

Penso che tu abbia bisogno di un modo per mantenere il contatore. Mi sembra che ogni volta che la chiamata di servizio viene avviata, il contatore viene ricreato.

Quindi è possibile salvare il contatore su un DB, un file flat o forse anche una variabile di sessione se si desidera che sia univoco per un utente.

+1

Penso che tu abbia frainteso i contatori delle prestazioni di Windows. Da qui: http://msdn.microsoft.com/en-us/library/aa373083(v=vs.85).aspx –

4

Quando si lavora con Contatori di prestazioni di tipo Average, vi sono due componenti: un numeratore e un denominatore. Poiché stai lavorando con una media, il contatore viene calcolato come "istanze x per istanze y". Nel tuo caso stai elaborando "articoli numerici" per "numero di secondi". In altre parole, è necessario contare sia il numero di elementi che si estrae dalla coda, sia il numero di secondi che devono essere rimossi.

I contatori delle prestazioni di tipo Average creano due contatori: un componente numeratore chiamato {name} e un componente denominatore denominato {name}Base. Se si passa allo snap-in Performance Counter, è possibile visualizzare tutte le categorie e i contatori; puoi controllare il nome del contatore Base.Quando si avvia il processo di elaborazione della coda, si dovrebbe

  • iniziare un cronometro
  • Articolo Rimuovi (s) dalla coda
  • fermare il cronometro
  • incremento del {name} contatore per il numero di elementi rimossi da la coda
  • incremento del contatore {name}Base dal numero delle zecche sul cronometro

Si suppone che il contatore sappia automaticamente dividere il primo contatore del secondo per dare il tasso medio. Controlla CodeProject per un buon esempio di come funziona.


È molto probabile che non si desideri questo tipo di contatore. Questi contatori Average vengono utilizzati per determinare il numero di istanze che si verificano al secondo delle operazioni; per esempio. il numero medio di secondi necessari per completare un ordine o per eseguire transazioni o processi complessi. Che cosa è desiderato è un numero medio di istanze in "tempo reale" rispetto al tempo di elaborazione.

Considerare se si disponesse di 1 articolo in coda e che occorresse rimuovere 1 ms, ovvero una velocità di 1000 articoli al secondo. Ma dopo un secondo hai rimosso solo 1 oggetto (perché è tutto quello che c'è) e quindi stai elaborando 1 oggetto al secondo in tempo reale. Allo stesso modo, se ci sono un milione di elementi in coda ma ne hai elaborato uno solo perché il tuo server è occupato a fare altri lavori, vuoi vedere 1000 articoli/secondo teorico o 1 elemento/secondo reale?

Se si desidera che questa cifra 'reale', in contrapposizione alla figura throughput teorico, allora questo scenario non è realmente adatto a contatori delle prestazioni - invece avete bisogno di sapere un orario di inizio e l'ora di fine, e un certo numero di articoli elaborati. Non può essere fatto con un semplice "contatore". Invece si dovrebbe memorizzare un tempo di avvio del sistema da qualche parte e calcolare (number of items)/(now - startup time).

+0

Ho appena realizzato che questa domanda ha un anno: -/ –

+1

Questa è una buona informazione, anche se non sono sicuro che questo risolva il problema dell'OP. I contatori di RateOfCountsPerSecond non hanno contatori di base.Questo contatore sembra una buona scelta per la situazione dell'OP - vuole solo vedere il numero totale di elementi rimosso fr om la coda nel secondo precedente. Non c'è alcuna media in corso - il contatore riporta solo quante volte il contatore è stato incrementato nell'ultimo secondo. –

+0

Sei assolutamente ASSOLUTAMENTE sicuro su come incrementare i contatori medi? Nel tuo esempio, dici di incrementare la base per il numero di tick, ma il progetto di codice collegato dice il contrario. '// incrementa il timer in base al costo dell'operazione _AverageDuration.IncrementBy (tick); // incremento contatore base solo da 1 _AverageDurationBase.Increment(); ' – Will

1

Ho avuto lo stesso problema. Nei miei test, credo che stavo vedendo il problema era una combinazione di multiistanza e velocità del conteggio al secondo. Se ho usato una singola istanza o un numero di elementi, ha funzionato. Qualcosa a proposito di questa combinazione di multiistanza e frequenza al secondo ha causato che fosse sempre zero.

Come menziona Performance counter of type RateOfCountsPerSecond64 has always the value 0, un riavvio può fare il trucco. Ha funzionato per me comunque.

Un'altra cosa che ha funzionato per me è stato questo l'inizializzazione del contatore in un blocco come questo:

counter.BeginInit(); 
counter.RawValue = 0; 
counter.EndInit(); 
Problemi correlati