2010-02-10 10 views
13

Tengo un servicio de Windows que sirve mensajes de alguna cola virtual a través de una interfaz de servicio WCF. quería exponer a dos contadores de rendimiento -Contador de tipo RateOfCountsPerSecond32 siempre muestra 0

  1. El número de elementos en la cola
  2. El número de elementos eliminados de la cola por segundo

El primero funciona bien, el segundo siempre se muestra como 0 en PerfMon.exe, a pesar de que RawValue parece ser correcto.

estoy creando los contadores como tal -

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

Luego, en cada llamada de servicio, que incrementar el contador correspondiente, para el contador por/seg este momento, parece que esto -

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

Como mencioné, si pongo un punto de interrupción después de la llamada para incrementar, puedo ver RawValue aumentando constantemente, en consistencia con las llamadas al servicio (con bastante frecuencia, más de una vez, creo) Pero el contador de rendimiento se mantiene en 0.

El contador de rendimiento que proporciona el recuento de elementos en la 'cola', que se implementa de la misma manera (aunque asigno RawValue, en lugar de llamar a Incremento) funciona bien.

¿Qué me estoy perdiendo?

+0

¿Está realmente creando una nueva * * contador cada vez que se incrementará? Eso no es correcto, solo crea uno. –

+0

Entonces, inicialmente no lo hice y todavía no funcionó, pero no creo que sea un problema como tal. De hecho, probé una muestra de la web (http://www.codeguru.com/columns/dotnet/article.php/c7279/), que funciona muy bien y la cambié para volver a crear el contador de rendimiento tiempo y todavía funciona (aunque estoy totalmente de acuerdo en que esta no es la manera más eficiente. De cualquier manera, como ya he dicho intenté ambas cosas, este es solo el estado del código en este momento porque sigo probando varias cosas. –

Respuesta

15

Al principio tuve problemas con este contador. MSDN tiene un ejemplo completo de trabajo que me ha ayudado mucho:

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

Como su ejemplo fue bastante largo aliento, que hierve abajo a un solo método para demostrar lo esencial. Cuando se ejecuta, veo el valor esperado de 10 cuentas por segundo en 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); 
    } 
} 

Espero que esto ayude a alguien.

+1

Gracias Mikey, ha pasado un tiempo y he avanzado, así que no puedo validar esto en mi código original, pero se ve bien, y es muy útil, ¡así que creo que 'merece' la respuesta! –

+0

@ Mike-Chamberlain, tengo un problema similar. Un contador de tipo NumberOfItems64, aunque se establece en un valor (una vez por minuto) se muestra en PerfMon como 0. En el depurador veo incrementado RawValue. Si solo hago clic en algo en el depurador, RawValue pasa a ser 0. La configuración del perf.counter se realiza en una aplicación ASP.NET. No puedo reproducir esto en casa en una aplicación de consola. Mi pregunta para usted: ¿tiene alguna conjetura cuál puede ser la razón de esto, y conoce alguna solución/solución? –

+0

Quizás la aplicación ASP.NET no tenga permisos para establecer o crear los contadores de ejecución. Puede intentar ejecutar la aplicación con derechos de administrador (solo con fines de prueba; cambie el usuario para el grupo de aplicaciones en el administrador de IIS). De hecho, no sé qué permisos son necesarios para crear o modificar contadores de rendimiento. – Palo

0

Creo que necesita alguna forma de conservar el contador. Me parece que cada vez que se inicia la llamada de servicio, se recrea el contador.

Para poder guardar el contador en una base de datos, archivo sin formato o incluso una variable de sesión si lo deseaba para un usuario.

+1

Creo que malinterpretas los contadores de rendimiento de Windows. Comenzando aquí: http://msdn.microsoft.com/en-us/library/aa373083(v=vs.85).aspx –

4

Cuando trabaje con Average escriba Contadores de rendimiento, hay dos componentes: un numerador y un denominador. Como trabaja con un promedio, el contador se calcula como 'x instancias por instancias y'. En su caso, usted está trabajando en 'números' por 'cantidad de segundos'. En otras palabras, necesita contar cuántos elementos saca de la cola y cuántos segundos tardan en eliminarse.

El tipo Average contadores de rendimiento en realidad crean dos contadores - un componente de numerador llamado {name} y un componente de denominador llamado {name}Base. Si va al complemento Contador de rendimiento, puede ver todas las categorías y contadores; puede verificar el nombre del contador Base.Cuando se inicia el proceso de procesamiento de la cola, que debiera

  • iniciar un elemento de eliminación
  • cronómetro (s) de la cola
  • detener el cronómetro
  • incremento de la {name} contador por el número de artículos retirados de la cola
  • incremento la {name}Base contador por el número de garrapatas en el cronómetro

Se supone que el contador debe saber automáticamente que se divide el primer contador por el segundo para obtener la tasa promedio. Consulte CodeProject para ver un buen ejemplo de cómo funciona esto.


Es bastante probable que no desee este tipo de contador. Estos contadores Average se usan para determinar cuántas instancias ocurren por segundo de operación; p.ej. la cantidad promedio de segundos que se tarda en completar un pedido o realizar una transacción o proceso complejo. Lo que desea puede querer es un número promedio de instancias en tiempo 'real' en comparación con el tiempo de procesamiento.

Considere si tenía 1 artículo en su cola, y le tomó 1ms para eliminar, eso es una tasa de 1000 artículos por segundo. Pero después de un segundo, solo eliminó 1 elemento (porque eso es todo lo que hay) y está procesando 1 artículo por segundo en tiempo "real". Del mismo modo, si hay un millón de artículos en la cola pero solo ha procesado uno porque su servidor está ocupado haciendo otro trabajo, ¿desea ver 1000 elementos/segundo teórico o 1 artículo/segundo real?

Si desea esta cifra 'real', en contraposición a la cifra de rendimiento teórico, este escenario no es realmente adecuado para contadores de rendimiento; en su lugar, debe conocer una hora de inicio y finalización, y una cantidad artículos procesados. Realmente no se puede hacer con un simple 'contador'. En cambio, almacenaría un tiempo de inicio del sistema en alguna parte y calcularía (number of items)/(now - startup time).

+0

Me acabo de dar cuenta de que esta pregunta tiene un año de antigüedad: -/ –

+1

Esta es una buena información, aunque no estoy seguro de que esto resuelva el problema del OP. Los contadores RateOfCountsPerSecond no tienen contadores base. Tal contador parece una buena opción para la situación del OP: solo quiere ver el número total de elementos eliminado fr om la cola en el segundo anterior. No hay promediación, el contador solo informa cuántas veces se ha incrementado el contador en el último segundo. –

+0

¿Está ABSOLUTAMENTE seguro de cómo incrementar los contadores promedio? En su ejemplo, dice incrementar la base por el número de tics, pero el proyecto de código vinculado dice lo contrario. '// incrementa el temporizador por el costo de tiempo de la operación _Duración media.IncrementoBy (marcas); // incrementar el contador base solo por 1 _AverageDurationBase.Increment(); ' – Will

1

Tuve el mismo problema. En mis pruebas, creo que estaba viendo que el problema era una combinación de múltiples instancias y la tasa de conteo por segundo. Si utilicé una sola instancia o una cantidad de elementos, el contador funcionó. Algo sobre esa combinación de múltiples instancias y velocidad por segundo causó que sea siempre cero.

Como menciona Performance counter of type RateOfCountsPerSecond64 has always the value 0, un reinicio puede hacer el truco. Trabajó para mí de todos modos.

Otra cosa que trabajó para mí era este inicializar el contador en un bloque de la siguiente manera:

counter.BeginInit(); 
counter.RawValue = 0; 
counter.EndInit(); 
Cuestiones relacionadas