2010-05-28 13 views
11

Tengo una aplicación Java ejecutándose en Sun 1.6 32-bit VM/Solaris 10 (x86)/Nahelem 8-core (2 hilos por núcleo).Minimizar el contexto del subproceso de Java Cambio de sobrecarga

Un caso de uso específico en la aplicación es para responder a algunos mensajes externos. En mi entorno de prueba de rendimiento, cuando preparo y envío la respuesta en el mismo hilo que recibe la entrada externa, obtengo una ventaja de aproximadamente 50 us que cuando entrego el mensaje a un hilo separado para enviar la respuesta. Uso un ThreadPoolExecutor con un SynchronousQueue para hacer el traspaso.

En su experiencia, ¿cuál es el retraso esperado de entre la programación de una tarea en un grupo de subprocesos y su recogida para su ejecución? ¿Qué ideas te han funcionado en el pasado para intentar mejorar esto?

Respuesta

0

No es la misma tarea, pero sí, la cola es general para ser utilizada en tareas de tiempo crítico. Nos hemos concentrado para evitar la sincronización para manejar eventos en absoluto. Revise las siguientes sugerencias

  • No utilice contenedores sincronizados (matrices, listas, mapas ...). Piense en contenedor por hilo.
  • Hemos utilizado un conjunto de hilos round-robin. Este conjunto consta de hilos preasignados y (!) Aparece exactamente una escucha para el evento sin ninguna cola. Cuando se produce un evento, el hilo se elimina de round-robin y otro se convierte en listener. Cuando se lleva a cabo el manejo, el hilo regresa al grupo.
+0

No creo que la mejor manera sea crear un nuevo hilo para cada evento entrante. Preferiría tener un threadpool fijo (quizás incluso escalado) que procese los eventos entrantes que se ponen en una lista por uno o más hilos oyentes – RecursiveExceptionException

+0

"... un nuevo hilo para cada evento entrante es la mejor manera" - ¿dónde lo hizo? ves esto en mi publicación, mientras escribía: "... round robin pool of threads"? – Dewfy

+0

Oh. Lo leí mal Solo vi "eliminar hilo" y pensé: "Sí, eso no es bueno": p – RecursiveExceptionException

11

El "retraso aceptable" depende completamente de su aplicación. Tratar con todo en el mismo hilo puede ayudar si tienes requisitos de latencia muy estrictos. Afortunadamente, la mayoría de las aplicaciones no tienen requisitos tan estrictos.

Por supuesto, si sólo un hilo es capaz de recibir solicitudes, basta con cerrar ese hilo para el cálculo de la respuesta, eso significará que ya no puede aceptar otras peticiones. Dependiendo de lo que esté haciendo, puede usar IO asíncrono (etc.) para evitar el modelo de "subprocesos por solicitud", pero es significativamente más difícil de OMI, y todavía termina con el cambio de contexto de subprocesos.

A veces es conveniente cola de solicitudes para evitar tener demasiados hilos procesándolas: si su manejo está vinculado a la CPU, no tiene mucho sentido tener cientos de subprocesos, es mejor tener una cola de tareas de productor/consumidor y distribuirlos en aproximadamente un hilo por núcleo. Eso es básicamente lo que hará ThreadPoolExecutor si lo configura correctamente, por supuesto. Eso no funciona tan bien si sus solicitudes pasan mucho tiempo esperando servicios externos (incluidos discos, pero principalmente otros servicios de red) ... en ese punto, o bien necesita utilizar modelos de ejecución asíncrona siempre que sea posible que haga un núcleo inactivo con una llamada de bloqueo, o toma el cambio de contexto de subproceso y tiene muchos subprocesos, confiando en el programador de subprocesos para que funcione lo suficientemente bien.

La conclusión es que los requisitos de latencia pueden ser difíciles: según mi experiencia, son mucho más estrictos que los requisitos de rendimiento, ya que son mucho más difíciles de escalar. Sin embargo, realmente depende del contexto.

+0

¡Gracias! Quise decir "esperado" en lugar de "aceptable". Quería hacerme una idea si 50 nosotros somos demasiado grandes o si se puede derribar. Sí, me gustaría liberar el hilo de recepción lo antes posible para poder recoger el siguiente mensaje. Además, el procesamiento de mi solicitud está vinculado a la CPU. –

1

¿Hay algún motivo por el que no utilice LinkedBlockingQueue para que su productor pueda poner en cola un par de elementos en lugar de SynchronousQueue? Por lo menos, tenga una cola con 1 artículo para que pueda obtener un mejor paralelismo.

¿Cuál es la velocidad del proceso de "preparación" frente a la "respuesta"? ¿Se puede usar un grupo de subprocesos para que varios subprocesos manejen las respuestas si son demasiado costosos?

2

50us suena algo alto para un traspaso, IME (Solaris 10/Opteron) LBQ normalmente está en el rango de 30-35us mientras que LTQ (LinkedTransferQueue) es aproximadamente 5us más rápido que eso. Como se indica en las otras respuestas, SynchronousQueue puede tender a ser un poco más lento porque la oferta no regresa hasta que el otro hilo haya tomado.

De acuerdo con mis resultados, Solaris 10 es marcadamente más lento que Linux en este momento que ve < 10us.

Realmente depende de algunas cosas, bajo la carga máxima

  • el número de solicitudes por segundo estás reparando?
  • ¿cuánto tiempo demora en procesar una solicitud?

Si conoce la respuesta a esas Qs, debería quedar bastante claro, en términos de rendimiento, si debe manejar el hilo receptor o el traspaso a un hilo de procesamiento.

Cuestiones relacionadas