Configuraciones de memoria con miles de hilos

Estoy jugando con la JVM (Oracle 1.7 64 bit) en una caja de Linux (AMD 6 Core, 16 GB de RAM) para ver cómo el número de subprocesos en una aplicación afecta el rendimiento. Espero medir en qué punto la conmutación de contexto degrada el rendimiento.

He creado una pequeña aplicación que crea un grupo de ejecución de subprocesos:

Executors.newFixedThreadPool(numThreads)

Yo ajustonumThreads Cada vez que ejecuto el programa, para ver el efecto que tiene.

Entonces presentonumThread trabajos (instancias dejava.util.concurrent.Callable) a la piscina. Cada uno incrementa unAtomicInteger, hace algún trabajo (crea una matriz de enteros aleatorios y lo baraja), y luego duerme un rato. La idea es simular una llamada de servicio web. Finalmente, el trabajo se vuelve a enviar a la piscina, de modo que siempre tengonumThreads trabajos que trabajan

Estoy midiendo el rendimiento, como en la cantidad de trabajos que se procesan por minuto.

Con varios miles de hilos, puedo procesar hasta 400,000 trabajos por minuto. Por encima de los 8000 hilos, los resultados comienzan a variar mucho, lo que sugiere que el cambio de contexto se está convirtiendo en un problema. Pero puedo continuar aumentando el número de subprocesos a 30,000 y aun así obtener un rendimiento más alto (entre 420,000 y 570,000 trabajos por minuto).

Ahora la pregunta: me sale unjava.lang.OutOfMemoryError: Unable to create new native thread Con más de unos 31.000 puestos de trabajo. He intentado configurar-Xmx6000M que no ayuda Intenté jugar con-Xss pero eso tampoco ayuda.

He leido esoulimit Puede ser útil, pero aumenta conulimit -u 64000 no cambió nada

Para información:

[root@apollo ant]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 127557
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Entonces, la pregunta # 1: ¿Qué debo hacer para poder crear un grupo de subprocesos más grande?

Pregunta n. ° 2: ¿En qué etapa debo esperar que el cambio de contexto realmente reduzca el rendimiento y haga que el proceso se detenga?

Aquí hay algunos resultados, después de que lo modifiqué para hacer un poco más de procesamiento (como se sugirió) y comencé a registrar los tiempos de respuesta promedio (como también se sugirió).

// ( (n_cores x t_request) / (t_request - t_wait) ) + 1
// 300 ms wait, 10ms work, roughly 310ms per job => ideal response time, 310ms
// ideal num threads = 1860 / 10 + 1 = 187 threads
//
// results:
//
//   100 =>  19,000 thruput,  312ms response, cpu < 50%
//   150 =>  28,500 thruput,  314ms response, cpu 50%
//   180 =>  34,000 thruput,  318ms response, cpu 60%
//   190 =>  35,800 thruput,  317ms response, cpu 65%
//   200 =>  37,800 thruput,  319ms response, cpu 70%
//   230 =>  42,900 thruput,  321ms response, cpu 80%
//   270 =>  50,000 thruput,  324ms response, cpu 80%
//   350 =>  64,000 thruput,  329ms response, cpu 90%
//   400 =>  72,000 thruput,  335ms response, cpu >90%
//   500 =>  87,500 thruput,  343ms response, cpu >95%
//   700 => 100,000 thruput,  430ms response, cpu >99%
//  1000 => 100,000 thruput,  600ms response, cpu >99%
//  2000 => 105,000 thruput, 1100ms response, cpu >99%
//  5000 => 131,000 thruput, 1600ms response, cpu >99%
// 10000 => 131,000 thruput, 2700ms response, cpu >99%,  16GB Virtual size
// 20000 => 140,000 thruput, 4000ms response, cpu >99%,  27GB Virtual size
// 30000 => 133,000 thruput, 2800ms response, cpu >99%,  37GB Virtual size
// 40000 =>       - thruput,    -ms response, cpu >99%, >39GB Virtual size => java.lang.OutOfMemoryError: unable to create new native thread

Los interpreto como:

1) Aunque la aplicación está inactiva durante el 96.7% del tiempo, aún queda mucho por hacer para cambiar de hilo. 2) El cambio de contexto es medible y se muestra en el tiempo de respuesta.

Lo interesante aquí es que al ajustar una aplicación, podría elegir el tiempo de respuesta aceptable, digamos 400 ms, y aumentar el número de subprocesos hasta que obtenga ese tiempo de respuesta, que en este caso permitiría que la aplicación procese alrededor de 95 mil solicitudes a minuto.

A menudo la gente dice que el número ideal de hilos está cerca del número de núcleos. En las aplicaciones que tienen tiempo de espera (subprocesos bloqueados, por ejemplo, esperando que responda una base de datos o un servicio web), el cálculo debe tenerlo en cuenta (consulte mi ecuación más arriba). Pero incluso ese ideal teórico no es un ideal real, cuando miras los resultados o cuando ajustas un tiempo de respuesta específico.

Respuestas a la pregunta(2)

Su respuesta a la pregunta