startindex significado ser que puede mayor longitud cadena c# performance async-await msmq

c# - significado - CPU subutilizada. Debido al bloqueo de E/S?



startindex no puede ser mayor que la longitud de la cadena (2)

Estoy tratando de encontrar dónde se encuentra el cuello de botella de una aplicación de servidor C # que infrautiliza la CPU. Creo que esto puede deberse a un bajo rendimiento de E / S del disco y no tiene nada que ver con la aplicación en sí, pero estoy teniendo problemas para sacar un hecho de esta suposición.

La aplicación lee los mensajes de una cola MSMQ local, realiza algún procesamiento en cada mensaje y, después de procesar los mensajes, envía mensajes de respuesta a otra cola local de MSMQ.

Estoy usando un bucle asíncrono para leer los mensajes de la cola, dequearlos lo más rápido posible y enviarlos para su procesamiento usando la tarea. Ejecutar para iniciar el procesamiento de cada mensaje (y no esperar en esta tarea. Ejecutar ... simplemente adjuntando una continuación solo cometió una falla al error de registro). Cada mensaje se procesa simultáneamente, es decir, no hay necesidad de esperar a que un mensaje se procese por completo antes de procesar el siguiente.

Al final del procesamiento de un mensaje, estoy usando el método Send de MessageQueue (de alguna manera asíncrono, pero no porque realmente tiene que esperar en la escritura del disco antes de volver -ver System.Messaging- porque MessageQueue no ofrece una versión asíncrona de Send )

Para los puntos de referencia, estoy haciendo cola de mensajes de 100K en la cola (aproximadamente 100 MB de tamaño total para 100 mil mensajes) y luego inicio el programa. En dos de mis computadoras personales (SSD HD en uno y SATA2 HD en el otro con i7 CPU quadcores -8 logico proc-) alcanzo ~ 95% de uso de CPU durante el ciclo de vida del programa (eliminando los mensajes de 100K, procesándolos y enviando respuestas). Los mensajes se descargan lo más rápido posible, se procesan lo más rápido posible (CPU involucrada aquí) y luego se responde por cada mensaje enviado a diferentes colas locales.

Ahora en una máquina virtual que ejecuta CPU de doble núcleo no HT (no tengo idea de cuál es el disco subyacente pero parece mucho menos eficiente que las minas ... durante el benchmark, con Perfmon puedo ver prom promedio de segundos / escribir alrededor de 10-15 ms en este VM, mientras que es alrededor de 2ms en mis máquinas personales) cuando estoy ejecutando el mismo banco, solo alcanzo ~ 55% de CPU (cuando estoy ejecutando el mismo banco en la máquina sin enviar mensajes de respuesta a la cola alcanzo ~ 90% CPU )

Realmente no entiendo cuál es el problema aquí. Parece claro que enviar el mensaje a la cola es el problema y ralentiza el procesamiento global del programa (y la eliminación de los mensajes que se procesarán), pero ¿por qué debería considerar que estoy usando Task.Run para iniciar el procesamiento de cada mensaje eliminado y, en última instancia, el envío de respuestas, no esperaría que la CPU se infrautilice. A menos que cuando un hilo esté enviando un mensaje, bloquee otros hilos para que se ejecuten en el mismo núcleo mientras espera la devolución (escritura en disco), en cuyo caso podría tener sentido considerando que la latencia es mucho mayor que en mis computadoras personales, pero un hilo la espera de E / S no debería impedir que se ejecuten otros subprocesos.

Realmente estoy tratando de entender por qué no estoy alcanzando al menos el 95% de uso de la CPU en esta máquina. Estoy diciendo ciegamente que esto se debe a un peor rendimiento de E / S de disco, pero aún no veo por qué conduciría a la subutilización de la CPU, ya que estoy ejecutando el procesamiento al mismo tiempo usando Task.Run. También podría tratarse de un problema del sistema completamente ajeno al disco, pero teniendo en cuenta que MessageQueue.Send parece ser el problema y que este método finalmente escribe mensajes en un archivo + disco asignado a la memoria, no veo de dónde podría venir el problema de rendimiento. que no sea disco

Por supuesto, es un problema de rendimiento del sistema ya que el programa maximiza el uso de la CPU en mis propias computadoras, pero necesito encontrar el cuello de botella exactamente en el sistema VM, y por qué exactamente está afectando la concurrencia / velocidad de mi aplicación.

Alguna idea ?


Para examinar la mala utilización del disco o de la CPU, solo hay una herramienta: Windows Performance Toolkit. Para ver un ejemplo de cómo usarlo, mira aquí . Debería obtener la última versión del SDK de Windows 8.1 (requiere .NET 4.5.1) que le ofrece la mayoría de las capacidades, pero la del SDK de Windows 8 también está bien.

Allí obtienes gráficos% de utilización de CPU y% de utilización de disco. Si alguno está al 100% y el otro es bajo, entonces ha encontrado el cuello de botella. Dado que es un generador de perfiles de todo el sistema, puede verificar si el servicio msmq está utilizando el disco incorrectamente o si usted u otra persona (por ejemplo, un escáner de virus es un problema común).

Puede acceder directamente a sus pilas de llamadas y comprobar qué proceso y subproceso despertó su subproceso de trabajo, que se supone que debe ejecutarse a toda velocidad. Luego puede ir al hilo y proceso de preparación y verificar lo que hizo antes de que pueda preparar su hilo. De esa forma, puede verificar directamente lo que lo estuvo obstaculizando durante tanto tiempo.

No más adivinanzas. Realmente puedes ver lo que está haciendo el sistema.

Para analizar más habilite en la Vista precisa de uso de CPU las siguientes columnas:

  • Nuevo proceso
  • NewThreadId
  • NewThreadStack (Etiquetas de marco)
  • ReadyingProcess
  • ReadyingThreadId
  • Ready (us) Sum
  • Espera (nosotros) Suma
  • Esperanos)
  • %Uso de CPU

A continuación, desglosa la pila de llamadas en tu proceso para ver dónde se producen las altas horas de espera (us) en un subproceso que se supone que debe ejecutarse a toda velocidad. Puedes acceder a un solo evento hasta que no puedas avanzar más. Luego verá los valores en Readying Process y ReadyingThreadId. Vaya a ese proceso / hilo (puede ser el suyo) y repita el proceso hasta que termine en alguna operación de bloqueo que involucre disco IO o duerme o una llamada de controlador de dispositivo de larga ejecución (por ejemplo, antivirus o el controlador vm).


Si los contadores de rendimiento de E / S de disco no se ven anormalmente altos, miraría luego al nivel del hipervisor. Asumiendo que está ejecutando exactamente el mismo código, el uso de una VM agrega latencia a toda la pila (CPU, RAM, Disco). Quizás pueda modificar la Programación de la CPU en el nivel del hipervisor y ver si esto aumentará la utilización de la CPU.

También consideraría usar un disco RAM temporalmente para las pruebas de rendimiento. Esto eliminaría la latencia de disco / SAN y podrá ver si eso soluciona su problema.