Pregunta

Estoy escribiendo un servidor, y me rama de cada acción de un hilo cuando la solicitud entrante.Hago esto porque casi cada solicitud que se hace la consulta de base de datos.Estoy usando un threadpool biblioteca para cortar la construcción/destrucción de hilos.

Mi pregunta es, a pesar de que - lo que es un buen punto de corte para subprocesos de e/S como estos?Sé que sólo sería una estimación aproximada, pero estamos hablando de cientos?miles?


EDITAR:

Gracias a todos por sus respuestas, me parece que voy a tener que probarlo para saber mi número de hilos de techo.La pregunta es, sin embargo:¿cómo puedo saber que he alcanzado ese techo?Lo que exactamente debo medir?

¿Fue útil?

Solución

Algunas personas dirían que dos hilos son demasiados, no estoy del todo en ese campo :-)

Aquí está mi consejo: medir, no adivinar. Una sugerencia es hacer que sea configurable e inicialmente configurarlo en 100, luego lanzar su software a la naturaleza y monitorear lo que sucede.

Si el uso de su hilo alcanza un máximo de 3, entonces 100 es demasiado. Si permanece en 100 durante la mayor parte del día, aumente hasta 200 y vea qué sucede.

Usted podría realmente hacer que su propio código monitoree el uso y ajuste la configuración para la próxima vez que se inicie, pero eso probablemente sea excesivo.


Para aclaraciones y elaboración:

No estoy abogando por rodar su propio subsistema de agrupación de subprocesos, por supuesto use el que tiene. Pero, dado que estaba preguntando acerca de un buen punto de corte para los subprocesos, supongo que la implementación de su grupo de subprocesos tiene la capacidad de limitar el número máximo de subprocesos creados (lo cual es algo bueno).

He escrito código de agrupación de conexiones de subprocesos y bases de datos y tienen las siguientes características (que creo que son esenciales para el rendimiento):

  • un número mínimo de hilos activos.
  • un número máximo de hilos.
  • cerrar hilos que no se han usado durante un tiempo.

El primero establece una línea base para un rendimiento mínimo en términos del cliente del grupo de subprocesos (este número de subprocesos siempre está disponible para su uso). El segundo establece una restricción en el uso de recursos por hilos activos. El tercero lo regresa a la línea de base en tiempos de silencio para minimizar el uso de recursos.

Debe equilibrar el uso de recursos de tener subprocesos no utilizados (A) con el uso de recursos de no tener suficientes subprocesos para hacer el trabajo (B).

(A) es generalmente el uso de memoria (pilas, etc.) ya que un hilo que no funciona no utilizará gran parte de la CPU. (B) generalmente será un retraso en el procesamiento de las solicitudes a medida que lleguen, ya que debe esperar a que un hilo esté disponible.

Por eso mides. Como usted dice, la gran mayoría de sus hilos esperarán una respuesta de la base de datos para que no se ejecuten. Hay dos factores que afectan la cantidad de hilos que debe permitir.

El primero es el número de conexiones DB disponibles. Este puede ser un límite difícil a menos que pueda aumentarlo en el DBMS. Asumiré que su DBMS puede tomar un número ilimitado de conexiones en este caso (aunque lo ideal sería medirlo también).

Entonces, el número de hilos que debería tener depende de su uso histórico. El mínimo que debe tener en ejecución es el número mínimo que ha tenido en ejecución + A%, con un mínimo absoluto de (por ejemplo, y hacerlo configurable como A) 5.

El número máximo de hilos debe ser su máximo histórico + B%.

También debe estar monitoreando los cambios de comportamiento. Si, por alguna razón, su uso llega al 100% de lo disponible durante un tiempo significativo (para que afecte el rendimiento de los clientes), debe aumentar el máximo permitido hasta que vuelva a ser B% más alto.


En respuesta a " ¿qué debo medir exactamente? " pregunta:

Lo que debe medir específicamente es la cantidad máxima de subprocesos en uso concurrente (por ejemplo, esperando un retorno de la llamada de DB) bajo carga. Luego agregue un factor de seguridad del 10% para el ejemplo (enfatizado, ya que otros carteles parecen tomar mis ejemplos como recomendaciones fijas).

Además, esto debe hacerse en el entorno de producción para el ajuste. Está bien obtener una estimación de antemano, pero nunca se sabe qué producción se le presentará (razón por la cual todas estas cosas deberían ser configurables en tiempo de ejecución). Esto es para detectar una situación como la duplicación inesperada de las llamadas entrantes del cliente.

Otros consejos

Esta pregunta se ha discutido a fondo y no tuve la oportunidad de leer todas las respuestas. Pero aquí hay algunas cosas a tener en cuenta al mirar el límite superior en el número de hilos simultáneos que pueden coexistir pacíficamente en un sistema dado.

  1. Tamaño de la pila de subprocesos: en Linux, el tamaño predeterminado de la pila de subprocesos es de 8 MB (puede usar ulimit -a para averiguarlo).
  2. Memoria virtual máxima que admite una variante de sistema operativo determinada. Linux Kernel 2.4 admite un espacio de direcciones de memoria de 2 GB. con Kernel 2.6, soy un poco más grande (3GB)
  3. [1] muestra los cálculos para el número máximo de subprocesos por VM máxima admitida. Para 2.4 resulta ser aproximadamente 255 hilos. para 2.6 el número es un poco más grande.
  4. Qué programador de kernel kindda tienes. Comparando el programador de kernel Linux 2.4 con 2.6, el último le ofrece una programación O (1) sin depender del número de tareas existentes en un sistema, mientras que el primero es más un O (n). Por lo tanto, también las capacidades SMP de la programación del núcleo también juegan un buen papel en el número máximo de subprocesos sostenibles en un sistema.

Ahora puede ajustar el tamaño de su pila para incorporar más subprocesos, pero luego debe tener en cuenta los gastos generales de la gestión de subprocesos (creación / destrucción y programación). Puede aplicar la afinidad de CPU a un proceso determinado, así como a un subproceso determinado para vincularlos a CPU específicas para evitar los gastos generales de migración de subprocesos entre las CPU y evitar problemas de liquidez.

Tenga en cuenta que uno puede crear miles de hilos a su antojo, pero cuando Linux se queda sin VM, comienza a matar procesos al azar (por lo tanto, hilos). Esto es para evitar que el perfil de la utilidad se maximice. (La función de utilidad informa sobre la utilidad de todo el sistema para una cantidad dada de recursos. Con recursos constantes en este caso CPU Cycles and Memory, la curva de la utilidad se aplana con más y más cantidad de tareas).

Estoy seguro de que el programador del kernel de Windows también hace algo de este tipo para lidiar con la utilización excesiva de los recursos

[1] http://adywicaksono.wordpress.com/2007/07/10/i-can-not-create-more-than-255-threads-on-linux-what-is-the-solutions/

Si sus hilos están realizando algún tipo de trabajo intensivo en recursos (CPU / Disco), rara vez verá beneficios más allá de uno o dos, y demasiados matarán el rendimiento muy rápidamente.

El "mejor de los casos" es que sus subprocesos posteriores se detendrán mientras se completan los primeros, o algunos tendrán bloques de bajo costo en recursos con poca contención. El peor de los casos es que comienzas a destruir la memoria caché / disco / red y tu rendimiento general cae por el suelo.

Una buena solución es colocar solicitudes en un grupo que luego se envían a los subprocesos de trabajo desde un grupo de subprocesos (y sí, evitar la creación / destrucción continua de subprocesos es un gran primer paso).

El número de subprocesos activos en este grupo se puede ajustar y escalar en función de los resultados de su creación de perfiles, el hardware en el que se está ejecutando y otras cosas que pueden estar ocurriendo en la máquina.

Una cosa que debe tener en cuenta es que python (al menos la versión basada en C) usa lo que se llama bloqueo global de intérpretes que puede tener un gran impacto en el rendimiento en máquinas multinúcleo.

Si realmente necesita sacar el máximo provecho de Python multiproceso, puede considerar usar Jython o algo así.

Como Pax dijo correctamente, mide, no adivines . Eso es lo que hice para DNSwitness y los resultados fueron sorprendentes: el número ideal de hilos era mucho mayor de lo que pensaba, algo así como 15,000 hilos para obtener los resultados más rápidos.

Por supuesto, depende de muchas cosas, por eso debes medirte.

Medidas completas (solo en francés) en Combien de fils d'ex & # 233; ¿precaución? .

He escrito varias aplicaciones muy multiproceso. En general, permito que un archivo de configuración especifique el número de subprocesos potenciales. Cuando ajusté a clientes específicos, configuré el número lo suficientemente alto como para que mi utilización de todos los núcleos de CPU fuera bastante alta, pero no tanto como para tener problemas de memoria (estos eran sistemas operativos de 32 bits en el tiempo).

Dicho de otra manera, una vez que llegue a un cuello de botella, ya sea CPU, rendimiento de la base de datos, rendimiento del disco, etc., agregar más hilos no aumentará el rendimiento general. Pero hasta que llegues a ese punto, ¡agrega más hilos!

Tenga en cuenta que esto supone que los sistemas en cuestión están dedicados a su aplicación, y no tiene que jugar bien (evite morir de hambre) a otras aplicaciones.

El "big iron" la respuesta es en general de un hilo por cada recurso limitado -- procesador (CPU), el brazo (I/O bound), etc -, pero eso sólo funciona si usted puede dirigir el trabajo para el subproceso correcto para el recurso al que se accede.

Donde eso no es posible, considere que tiene fungibles recursos (Cpu) y no fungibles recursos (armas).Para CPUs no es crítico para asignar a cada hilo específico de la CPU (aunque ayuda con la gestión de caché), pero para los brazos, si no se puede asignar un hilo para el brazo, te metes en la cola de la teoría y lo que el número óptimo para mantener los brazos ocupados.En general estoy pensando que si usted no puede enrutar las solicitudes basadas en el brazo que se emplea, entonces tienen 2 o 3 hilos por el brazo que va a ir a la derecha.

Una complicación que se produce cuando la unidad de trabajo aprobado para el hilo no se ejecuta razonablemente una unidad atómica de trabajo.Por ejemplo, usted puede tener el hilo en un punto de acceso a la disco, en otro punto de espera en una red.Esto aumenta el número de "grietas", donde los subprocesos adicionales pueden entrar y hacer un trabajo útil, pero también aumenta la oportunidad para que los subprocesos adicionales para contaminar cada una de las otras cachés, etc, y el consejo directivo del sistema.

Por supuesto, usted debe sopesar todo esto contra el "peso" de un hilo.Desafortunadamente, la mayoría de los sistemas tienen muy pesado hilos (y lo que ellos llaman "ligero hilos" a menudo no son los hilos en todos), así que es mejor errar en el lado de baja.

Lo he visto en la práctica es que muy sutiles diferencias pueden hacer una enorme diferencia en la cantidad de subprocesos que son óptimos.En particular, caché de los problemas y conflictos de bloqueo puede limitar mucho la cantidad de práctica de la concurrencia.

Una cosa a considerar es cuántos núcleos existen en la máquina que ejecutará el código. Eso representa un límite estricto sobre cuántos subprocesos pueden continuar en un momento dado. Sin embargo, si, como en su caso, se espera que los subprocesos esperen con frecuencia que una base de datos ejecute una consulta, es probable que desee ajustar sus subprocesos en función de cuántas consultas simultáneas puede procesar la base de datos.

Creo que esto es un poco esquivo a su pregunta, pero ¿por qué no dividirlos en procesos? Mi comprensión de las redes (desde los días nebulosos de antaño, en realidad no codifico redes en absoluto) fue que cada conexión entrante se puede manejar como un proceso separado, porque si alguien hace algo desagradable en su proceso, no lo hace. bombardea todo el programa.

ryeguy, actualmente estoy desarrollando una aplicación similar y mi número de subprocesos está configurado en 15. Desafortunadamente, si lo aumento a 20, se bloquea. Entonces, sí, creo que la mejor manera de manejar esto es medir si su configuración actual permite o no más o menos que un número X de hilos.

En la mayoría de los casos, debe permitir que el grupo de subprocesos se encargue de esto. Si publica algún código o proporciona más detalles, podría ser más fácil ver si hay alguna razón por la cual el comportamiento predeterminado del grupo de subprocesos no sería el mejor.

Puede encontrar más información sobre cómo debería funcionar aquí: http://en.wikipedia.org / wiki / Thread_pool_pattern

Tantos hilos como núcleos de CPU es lo que he escuchado muy a menudo.

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