2008-09-19 19 views
19

Me pregunto, que tan caro es tener muchos hilos en estado de espera en java 1.6 x64.Cuantos recursos consumen los hilos para dormir y para esperar

Para ser más específicos, estoy escribiendo una aplicación que se ejecuta en muchas computadoras y envía/recibe datos de una a otra. Me siento más cómodo al tener un hilo separado para cada máquina y tarea conectada, como 1) enviar datos, 2) recibir datos, 3) restablecer la conexión cuando se cae. Entonces, dado que hay N nodos en el clúster, cada máquina tendrá 3 subprocesos para cada uno de los N-1 vecinos. Normalmente habrá 12 máquinas, lo que equivale a 33 hilos de comunicación.

La mayoría de estos hilos estarán durmiendo la mayor parte del tiempo, por lo que para optimizarlos podría reducir el número de hilos y darle más trabajo a cada uno de ellos. Como por ejemplo. restablecer la conexión es responsabilidad de recibir el hilo. O el envío a todas las máquinas conectadas se realiza por un solo hilo.

Entonces, ¿hay algún impacto significativo en el rendimiento al tener muchos hilos para dormir?

Respuesta

15

En la mayoría de los casos, los recursos consumidos por un hilo que duerme será su espacio de pila. Usar un modelo de 2 hilos por conexión, que creo que es similar a lo que describes, causa graves problemas de escalabilidad por esta misma razón cuando la cantidad de conexiones crece.

He estado en esta situación yo mismo, y cuando el número de conexiones creció por encima de 500 conexiones (alrededor de mil subprocesos), en muchos casos obtienes OutOfMemoryError, ya que el uso de espacio de pila de subprocesos excede la cantidad máxima de memoria para un solo proceso. Al menos en nuestro caso, que estaba en un mundo de Windows con Java de 32 bits. Puedes sintonizar cosas y llegar un poco más allá, supongo, pero al final no es muy escalable ya que desperdicias mucha memoria.

Si necesita una gran cantidad de conexiones, Java NIO (IO nuevo o lo que sea) es el camino a seguir, lo que permite manejar muchas conexiones en el mismo hilo.

Habiendo dicho eso, no debe encontrar un gran problema con menos de 100 hilos en un servidor razonablemente moderno, incluso si es probable que todavía sea una pérdida de recursos.

+0

No debería utilizar JRocikt JVM resolver estos problemas, ya que he leído que fue diseñado para manejar miles de subprocesos. –

+0

No tengo experiencia alguna con JRockit JVM, así que realmente no puedo comentar sobre eso. Habiendo dicho eso, sé que la mayoría de los sistemas operativos funcionarán mal con miles de hilos, así que no sé cómo JRockit soluciona ese problema ... – Liedman

+0

Los servidores de 64 bits son la norma ahora. Me pregunto si OOM debido a los grandes requisitos de espacio de direcciones no es un problema. – Raedwald

1

Esto no se escalará muy bien. Tener una gran cantidad de subprocesos significa que la VM debe pasar más tiempo cambiando el contexto, y el uso de la memoria será mayor debido a que cada subproceso requiere su propio espacio de pila. Sería mejor con un menor número de subprocesos de procesamiento en forma de canalización, o utilizar el grupo de subprocesos con técnicas asíncronas.

+1

¿Está seguro de que los subprocesos en el estado de espera aumentan la sobrecarga de cambio de contexto? – Grigory

1

Muchos subprocesos equivalen a montones de espacio de pila, lo que consumirá tu memoria. Revisa tu configuración de -Xss para saber cuánto, luego haz los cálculos.

Y si alguna vez tiene que hacer un notifyAll() por alguna razón, entonces, por supuesto, está despertando un montón de hilos adicionales, aunque puede que no tenga que hacer eso en su arquitectura propuesta.

No estoy seguro de que pueda evitar fácilmente tener un hilo por socket en este modelo (aunque sé muy poco acerca de NIO, que podría solucionar incluso ese problema), pero eche un vistazo a la interfaz java.util.concurrent.Executor y su implementación clases de una manera decente para evitar tener demasiados hilos adicionales dando vueltas. De hecho, el ThreadPoolExecutor podría ser una buena manera de administrar sus hilos de escucha también, por lo que no perderá mucho tiempo creando y destruyendo hilos innecesariamente.

2

Tuvimos el mismo problema mucho antes de cambiar a NIO, por lo que voy a secundar la recomendación de Liedmans para ir con ese marco.Debería poder encontrar un tutorial, pero si quiere los detalles, puedo recomendar Java NIO por Ron Hitchens.

Swithcing to NIO aumentó la cantidad de conexiones que podíamos manejar mucho, lo cual fue realmente crítico para nosotros.

0

De las pruebas que he realizado en C, Lua y Python, puede hacer su propia función de espera o espera con muy pocas líneas de códigos para hacer un bucle ligero y simple. Usa una variable local con el tiempo futuro que deseas alcanzar y luego prueba la marca de tiempo actual en un ciclo while. Si se encuentra en un ámbito en el que trabaja con fps, ejecute la función de espera una vez por cuadro para ahorrar en recursos. Cuanta más precisión necesita, considere usar el reloj en lugar de la marca de tiempo, ya que la marca de tiempo está limitada a segundos. Cuantas más líneas de código añades a una función de espera, menos precisa se vuelve y más recursos consume, aunque cualquier cosa por debajo de 10 líneas debe ser lo suficientemente rápida.

Cuestiones relacionadas