Demasiados Threads Bajan el Rendimiento


Es bueno notar que hay que seleccionar correctamente el nivel de concurrencia de las aplicaciones de acuerdo al hardware en el que se van a ejecutar.

Si se tienen muchos thread compitiendo por el tiempo de las o las CPUs se pierde mucho tiempo en la selección de qué thread se ejecuta y el context switching.

En la aplicación que me ocupa, se usan varios threads para aprovechar los tiempos de espera al leer y escribir de la base de datos. Como al hacer una consulta, el driver se duerme a la espera de que haya datos que leer desde el socket, otros thread puede pedir una escritura o hacer un procesamiento de algo leído ateriormente. Además disponemos de un hardware con 2 procesadores Xeon.

La idea era tener una thread que esté continuamente leyendo datos de a lotes y poniéndlos en una cola para ser procesados, un conjunto de threads procesando los lotes leídos y poniéndolos en otra cola y un thread the lea de esa última cola y los escriba en la base.

En un primer momento se detectó que el tiempo de procesamiento estaba muy fuertemente determinado por el tiempo de lectura, es decir, todos los demás threads estaban a la espera de que hubiera algo que procesar en casi todo momento.

Se contraron los esfuerzos en mejorar la consulta de lectura y ¡oh sorpresa!, el tiempo de lectura se redujo, pero el tiempo total aumentó.

  • Antes: 18.262.559 registros en 40.753 segundos.
  • Después: 12.070.144 registros en 56.271 segundos.

Menos registros insumen más tiempo, sin embargo los tiempos de cada etapa de la tarea eran menores:

  • Antes: lectura 1.454, escritura 25.804 y procesamiento 814
  • Después: lectura 913, escritura 14.082 y procesamiento 221

¿Entonces procesando un 33% menos de registros y con una consulta un poco mejor los tiempos de lectura, procesamiento y escritura se reducen, pero el tiempo total aumenta? ¿En qué se perdió ese tiempo? El tiempo de lectura contempla desde que se realiza la consulta hasta que se ha leído el lote completo. El tiempo de procesamiento contenpla desde que se toma el lote hasta que se lo deposita para ser escrito y el tiempo de escritura desde que se lo toma hasta que se lo ha escrito completamente. Si en cada uno de los procesos el thread es detenido porque otro thread necesita la CPU, ese tiempo se está contabilizando doble. Por ejemplo si mientras se escribe un lote se lee otro.

Mi teoría es que ese tiempo es overhead por tener 6 threads (1 lee, 1 escribe y 4 procesan) con 2 procesadores. Mucha competencia hace que se pierda mucho tiempo de procesamiento.

Reduje en número de threads que hacen procesamiento a 2. Si observo una mejora en los números, probaré con sólo 1 thread que procese.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s