Do Linux JVMs actually implement Thread priorities?
Wrote a quick Java proggy to spawn 10 threads with each priority and calculate pi (4*atan(1) method) with BigDecimals 500,000 times each, join on each thread and report the elapsed time for run method. Yeah, prob'ly not the best example, but keeping it basic.
I'm aware of Bug4813310
It is non-trivial to do in C, but can we assume that native priorities are never set on Linux JVMs?
$uname -r && grep bogomips /proc/cpuinfo
2.4.33.3
bogomips : 43开发者_开发知识库12.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
Looks like not much of a deviation that one would expect! That was on a small virtual Linux machine. Maybe just Sun's? We shall try IBM J9 VM:
1:4091
2:4142
3:3957
4:3905
5:3984
6:3985
7:4130
8:4055
9:3752
10:4071
The gross numbers look pretty good in comparison, but there is no scale to the numbers from a thread priority perspective.
Let's try 500k iterations on a 2.6 kernel with an older Sun JVM, one that is constantly loaded with load averages rarely below 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
Let's try IBM's J9 on a real slab just with 2.6 kernel and since a bigger system I'll increase iterations to 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
Some great times, but still no apparent thread/process priorities.
Let's try a Windows box. I know that Windows has a fairly aggressive thread priority scheme. Anything above normal anecdotaly consumes much more. As such, let's move to 900,000 iterations in each thread:
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
Very much what we're looking for, no?
So Linux JVM's apparently don't have thread priority? I understand that you can't really renice to a lower nice level in C, but I would assume JVM engineers would have figured out how to keep a low-niced dispatcher of sorts.
From the JDK 8 source code, a comment reads:
////////////////////////////////////////////////////////////////////////////////
// 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.
...
Later on, we see:
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;
}
}
if (UseCriticalJavaThreadPriority) {
os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority];
}
return 0;
}
...
And subsequently:
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;
}
So! At least on Sun Java, on Linux, you won't see thread priorities unless you have done -XX:ThreadPriorityPolicy
and that seems to require root.
Just a shot in the dark here, but wouldn't having prioritized threads in the JVM require having the ability to adjust the priority of the operating system threads?
Linux (and any Unix-like OS) limits the ability to give processes higher priority to root. I would think there would be a similar limitation on threads.
The default Linux thread scheduler policy SCHED_OTHER does not support priorities. Or to be more exact, it support a priority setting with one value: 0. The other so called 'real time' policies SCHED_FIFO and SCHED_RR support higher priorities, but are only available to processes with super user privileges.
精彩评论