java multithreading jvm thread-priority

java - ¿Las JVM de Linux realmente implementan las prioridades de subprocesos?



multithreading thread-priority (3)

Escribió un rápido programa de Java para engendrar 10 hilos con cada prioridad y calcular el método pi (4 * atan (1)) con BigDecimals 500,000 veces cada uno, unir cada hilo e informar el tiempo transcurrido para el método de ejecución. Sí, probablemente no sea el mejor ejemplo, pero mantenerlo básico.

Estoy al tanto de Bug4813310

No es trivial hacerlo en C, pero ¿podemos suponer que las prioridades nativas nunca se establecen en las JVM de Linux?

$uname -r && grep bogomips /proc/cpuinfo 2.4.33.3 bogomips : 4312.26 $java -version 2>&1 |head -1 Java version "1.6.0_01" $javac T.java && java -Xmx32m -XX:+UseThreadPriorities T 1:3112 2:2636 3:2662 4:3118 5:2870 6:3319 7:3412 8:3304 9:3299 10:3069

¡Parece que no hay una desviación que uno esperaría! Eso fue en una pequeña máquina virtual de Linux. Tal vez solo Sun''s? Intentaremos IBM J9 VM:

1:4091 2:4142 3:3957 4:3905 5:3984 6:3985 7:4130 8:4055 9:3752 10:4071

Los números brutos se ven bastante bien en comparación, pero no hay escala para los números desde una perspectiva de prioridad de subprocesos.

Probemos 500k iteraciones en un kernel 2.6 con una antigua JVM de Sun, una que se carga constantemente con promedios de carga raramente por debajo de 7:

$uname -r && grep bogomips /proc/cpuinfo 2.6.9-67.ELsmp bogomips : 3992.93 bogomips : 3990.00 $java -version 2>&1 |head -1 java version "1.4.2_14" $javac T.java && java -Xmx32m -XX:+UseThreadPriorities T 1:63200 2:64388 3:62532 4:58529 5:62292 6:64872 7:64885 8:64584 9:61653 10:61575

Probemos el J9 de IBM en una losa real solo con kernel 2.6 y dado que un sistema más grande aumentaré las iteraciones a 2,000,000.

$uname -r && grep bogomips /proc/cpuinfo 2.6.9-78.ELsmp bogomips : 5989.03 bogomips : 5985.03 bogomips : 5985.01 bogomips : 5985.02 bogomips : 5984.99 bogomips : 5985.02 bogomips : 5984.99 bogomips : 5985.02 $java -Xmx32m T # this is the IBM J9 1:1718 2:1569 3:1989 4:1897 5:1839 6:1688 7:1634 8:1552 9:2027 10:1522

Algunos buenos momentos, pero todavía no hay prioridades evidentes de rosca / proceso.

Probemos un cuadro de Windows. Sé que Windows tiene un esquema de prioridades de subprocesos bastante agresivo. Cualquier cosa por encima de lo anecdótico normal consume mucho más. Como tal, pasemos a 900,000 iteraciones en cada hilo:

C:/>java -version java version "1.6.0_11" C:/>java -Xmx32m T 1:12578 2:12625 3:11469 4:11453 5:10781 6:8937 7:10516 8:8406 9:9953 10:7391

Mucho de lo que estamos buscando, ¿no?

Entonces, ¿las JVM de Linux aparentemente no tienen prioridad de subprocesos? Entiendo que realmente no se puede renice a un nivel más bajo en C, pero supongo que los ingenieros de JVM habrían descubierto cómo mantener a un despachador de poca monta.


Bueno, veamos la fuente :

línea 2947:

//////////////////////////////////////////////////////////////////////////////// // thread priority support // Note: Normal Linux applications are run with SCHED_OTHER policy. SCHED_OTHER // only supports dynamic priority, static priority must be zero. For real-time // applications, Linux supports SCHED_RR which allows static priority (1-99). // However, for large multi-threaded applications, SCHED_RR is not only slower // than SCHED_OTHER, but also very unstable (my volano tests hang hard 4 out // of 5 runs - Sep 2005). // // The following code actually changes the niceness of kernel-thread/LWP. It // has an assumption that setpriority() only modifies one kernel-thread/LWP, // not the entire user process, and user level threads are 1:1 mapped to kernel // threads. It has always been the case, but could change in the future. For // this reason, the code should not be used as default (ThreadPriorityPolicy=0). // It is only used when ThreadPriorityPolicy=1 and requires root privilege.

...

línea 2982:

static int prio_init() { if (ThreadPriorityPolicy == 1) { // Only root can raise thread priority. Don''t allow ThreadPriorityPolicy=1 // if effective uid is not root. Perhaps, a more elegant way of doing // this is to test CAP_SYS_NICE capability, but that will require libcap.so if (geteuid() != 0) { if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy)) { warning("-XX:ThreadPriorityPolicy requires root privilege on Linux"); } ThreadPriorityPolicy = 0; } } return 0; }

...

línea 2997:

OSReturn os::set_native_priority(Thread* thread, int newpri) { if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK; int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri); return (ret == 0) ? OS_OK : OS_ERR; }

¡Asi que! Al menos en Sun Java, en Linux, no verá las prioridades de subprocesos a menos que haya hecho -XX:ThreadPriorityPolicy y que parezca requerir root.


La política predeterminada del programador de hilos de Linux SCHED_OTHER no admite prioridades. O para ser más exactos, admite una configuración de prioridad con un valor: 0. Las otras políticas denominadas de "tiempo real" SCHED_FIFO y SCHED_RR admiten prioridades más altas, pero solo están disponibles para procesos con privilegios de superusuario.


Solo un disparo en la oscuridad aquí, pero ¿no tendrían subprocesos priorizados en la JVM que requieren la capacidad de ajustar la prioridad de los hilos del sistema operativo?

Linux (y cualquier sistema operativo tipo Unix) limita la capacidad de dar a los procesos una mayor prioridad a la raíz. Creo que habría una limitación similar en los hilos.