2009-11-02 5 views
24

Написал быстрый Java proggy, чтобы создать 10 потоков с каждым приоритетом и вычислить метод pi (4 * atan (1)) с BigDecimals 500 000 раз каждый, присоединиться к каждому потоку и сообщить об истекшем времени для запуска метода. Да, наверное, не лучший пример, но сохраняя его базовым.Действительно ли Linux JVM реализуют приоритеты потоков?

Я знаю Bug4813310

Это нетривиально сделать в C, но мы можем предположить, что местные приоритеты никогда не установлены на 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 

Похоже, что это не так много отклонений, которых можно было бы ожидать! Это было на небольшой виртуальной машине Linux. Может быть, просто Солнце? Постараемся IBM J9 VM:

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

Грубые цифры выглядят довольно хорошо в сравнении, но нет шкалы с числами от приоритета нити перспективы в.

Давайте попробуем 500K итераций на ядре 2.6 с более старым Sun JVM, тот, который постоянно загружен со средними значениями нагрузки редко ниже 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 

Давайте попробуем J9 компании IBM на реальный слябе только с ядром 2.6 и так как большая система увеличит итерации до 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 

Некоторые замечательные времена, но все еще нет видимых нитей/приоритетов процесса.

Давайте попробуем коробку Windows. Я знаю, что Windows имеет довольно агрессивную схему приоритетов потоков. Все, что выше нормальное anecdotaly потребляет гораздо больше. Таким образом, давайте переместимся на 900 000 итераций в каждом потоке:

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 

Очень то, что мы ищем, нет?

Итак, у Linux JVM, по-видимому, нет приоритета потока? Я понимаю, что вы действительно не можете поменять себя на более низкий уровень на C, но я бы предположил, что инженеры JVM выяснили бы, как сохранить низкоуровневый диспетчер.

ответ

20

Ну, давайте посмотрим на the source:

линия 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. 

...

линия 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; 
} 

...

линия 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; 
} 

Так! По крайней мере, на Sun Java, в Linux, вы не увидите приоритетов потоков, если вы не сделали -XX:ThreadPriorityPolicy, и это, кажется, требует root.

+4

Я тоже думал об этом. Переход на корень с помощью UseThreadPriorities ничего не сказался. Однако, как корень и '-XX: ThreadPriorityPolicy = 1 'yeilds: 1: 3809 2: 3587 3: 3679 4: 3223 5: 2796 6: 2686 7: 2233 8: 1895 9: 1759 10: 2311 Глядя хорошо :) – Xailor

+0

поддавки -XX: ThreadPriorityPolicy значение = 0 и = 1 также позволит вам поднять темы Прио – Schildmeijer

0

Просто выстрел в темноте здесь, но не имеющий приоритетных потоков в JVM, необходимо иметь возможность настроить приоритет потоков операционной системы?

Linux (и любая Unix-подобная ОС) ограничивает возможность предоставления процессам более высокого приоритета root. Я думаю, что будет такое же ограничение на потоки.

+0

Верно, вы можете восстановить себя, просто не вниз. Я бы подумал, однако, что поток/процесс отправки может изменить 10 уровней UPWARDS, где они есть. Возможно, даже (gasp) есть отдельный корневой демона, который будет назначать приоритеты для потоков JVM. – Xailor

+0

Я не знаю о Java, но в .NET управляемые потоки не совпадают с потоками ОС, то есть CLR планирует потоки самостоятельно. Поэтому это должно быть возможно и для JVM. – OregonGhost

+0

Я не думаю, что CLR использует зеленые потоки. Я почти уверен, что планирование потоков выполняется ОС. – jassuncao

1

Политика планировщика потоков Linux по умолчанию SCHED_OTHER не поддерживает приоритеты. Или, точнее, он поддерживает настройку приоритета с одним значением: 0. Другие так называемые политики реального времени SCHED_FIFO и SCHED_RR поддерживают более высокие приоритеты, но доступны только для процессов с привилегиями суперпользователя.

+0

Что это должно означать от другого фрагмента кода '! SCHED_OTHER // поддерживает только динамический приоритет' – Xailor

+0

SCHED_OTHER поддерживает только тонкость, что является подсказкой планировщик о том, как устанавливать приоритеты потоков и процессов. –