Pregunta

Estoy perfilando un programa multiproceso que se ejecuta con diferentes números de subprocesos permitidos. A continuación se muestran los resultados de rendimiento de tres ejecuciones del mismo trabajo de entrada.

1 thread:
  Total thread time: 60 minutes.
  Total wall clock time: 60 minutes.

10 threads:
  Total thread time: 80 minutes. (Worked 33% longer)
  Total wall clock time: 18 minutes.  3.3 times speed up

20 threads
  Total thread time: 120 minutes. (Worked 100% longer)
  Total wall clock time: 12 minutes.  5 times speed up

Dado que se necesita más tiempo de hilo para hacer el mismo trabajo, creo que los hilos deben competir por recursos.

Ya examiné los cuatro pilares (cpu, memoria, diskIO, red) tanto en la máquina de la aplicación como en el servidor de la base de datos. La memoria era el recurso original en disputa, pero ahora está arreglado (más de 1G gratis en todo momento). La CPU oscila entre el 30% y el 70% en la prueba de 20 hilos, por lo que hay mucho. diskIO es prácticamente nulo en la máquina de la aplicación y mínimo en el servidor de la base de datos. La red es realmente genial.

También he creado un perfil de código con redgate y no veo métodos esperando bloqueos. Ayuda que los hilos no compartan instancias. Ahora estoy comprobando elementos más matizados como el establecimiento / agrupación de la conexión de la base de datos (si 20 subprocesos intentan conectarse a la misma base de datos, ¿tienen que esperar el uno al otro?).

Estoy intentando identificar y abordar la disputa de recursos, de modo que la ejecución de 20 subprocesos se vea así:

20 threads
  Total thread time: 60 minutes. (Worked 0% longer)
  Total wall clock time: 6 minutes.  10 times speed up

¿Cuáles son las fuentes más probables (además de las 4 grandes) que debería buscar para encontrar ese argumento?


El código que realiza cada hilo es aproximadamente:

Run ~50 compiled LinqToSql queries
Run ILOG Rules
Call WCF Service which runs ~50 compiled LinqToSql queries, returns some data
Run more ILOG Rules
Call another WCF service which uses devexpress to render a pdf, returns as binary data
Store pdf to network
Use LinqToSql to update/insert. DTC is involved: multiple databases, one server.

Los servicios WCF se ejecutan en la misma máquina y no tienen estado y pueden manejar múltiples solicitudes simultáneas.


La máquina tiene 8 CPU.

¿Fue útil?

Solución

Lo que describe es que desea una escalabilidad de un 100% que sea una relación 1: 1 entre el aumento de subprocesos y la disminución del tiempo de bloqueo de pared ... este suele ser un objetivo, pero difícil de alcanzar ...

Por ejemplo, escribe que no hay contención de memoria porque hay 1 GB libre ... esto es en mi humilde opinión una suposición incorrecta ... la contención de memoria también significa que si dos subprocesos intentan asignar memoria, podría suceder que uno tenga que espere el otro ... otro punto a tener en cuenta son las interrupciones que ocurren por GC que congela todos los hilos temporalmente ... el GC se puede personalizar un poco a través de la configuración (gcServer) - ver http://blogs.msdn.com/b/clyon/archive/2004/09/08 /226981.aspx

Otro punto es el servicio WCF llamado ... si no se puede escalar, por ejemplo, la representación de PDF, entonces esa también es una forma de contención, por ejemplo ...

La lista de posibles disputas es "interminable" ... y casi nunca en las áreas obvias que mencionaste ...

EDITAR - según los comentarios:

Algunos puntos para verificar:

  • agrupación de conexiones
    que proveedor utilizas? ¿cómo está configurado?
  • Representación de PDF
    la posible contención se mediría en algún lugar dentro de la biblioteca que usa ...
  • Linq2SQL
    Verifique los planes de ejecución para todas estas consultas ... puede ser que algunas tomen cualquier tipo de bloqueo y, por lo tanto, posiblemente creen una contención DB-server-side ...

EDICIÓN 2:

Hilos
¿Son estos hilos del ThreadPool? Si es así, no escalará :-(

EDITAR 3:

Los subprocesos de ThreadPool son malos para tareas de larga duración, como es el caso en su escenario ... para obtener más detalles, consulte

De http://www.yoda.arachsys.com/csharp/ threads / printable.shtml

Las operaciones de ejecución prolongada deben utilizar subprocesos recién creados; Las operaciones de ejecución corta pueden aprovechar el grupo de subprocesos.

Si desea un rendimiento extremo, podría valer la pena consultar CQRS y el real- ejemplo mundial descrito como LMAX .

Otros consejos

En lugar de medir el tiempo total del subproceso, mida el tiempo para cada una de las operaciones que realiza que realizan E / S de algún tipo (base de datos, disco, red, etc.).

Sospecho que va a encontrar que estas operaciones son las que toman más tiempo cuando tiene más subprocesos, y esto se debe a que la contención está en el otro extremo de esa E / S.Por ejemplo, su base de datos podría estar serializando solicitudes de consistencia de datos.

sí, hay disputa de recursos. Todos los hilos tienen que leer / escribir datos en el mismo bus de memoria, dirigidos a los mismos módulos RAM, por ejemplo. No importa cuánta RAM esté libre, importa que las lecturas / escrituras las realice el mismo controlador de memoria en los mismos módulos RAM y que los datos se transporten por el mismo bus.

Si hay algún tipo de sincronización en cualquier lugar , entonces ese también es un recurso en disputa. Si hay alguna E / S, es un recurso en disputa.

Nunca verá una aceleración N x al pasar de 1 a N subprocesos. No es posible porque, en última instancia, todo en la CPU es un recurso compartido sobre el que habrá cierto grado de contención.

Hay muchos factores que le impiden obtener la aceleración lineal completa. Está asumiendo que la base de datos, el servidor en el que se ejecuta la base de datos, la red que la conecta al cliente, la computadora cliente, el sistema operativo y los controladores en ambos extremos, el subsistema de memoria, E / S de disco y todo in between es capaz de ir 20 veces más rápido cuando se pasa de 1 a 20 hilos.

Dos palabras: sigue soñando.

Cada uno de estos cuellos de botella solo tiene que reducir su velocidad en un pequeño porcentaje, entonces el resultado general será algo parecido a lo que está viendo.

Estoy seguro de que puedes modificarlo para escalar un poco mejor, pero no esperes milagros.

Pero una cosa que puede buscar es compartir líneas de caché. ¿Los hilos acceden a datos que están muy cerca de los datos utilizados por otros hilos? ¿Con qué frecuencia puede evitar que eso ocurra?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top