2009-11-18 3 views
1

У меня есть сеть потоков Java (потоковое программирование), осуществляющая связь через каналы с фиксированной пропускной способностью - работает под управлением WindowsXP. То, что мы ожидали, основываясь на нашем опыте с «зелеными» потоками (без превентивного), будет заключаться в том, что потоки будут переключать контекст реже (тем самым уменьшая время процессора), если каналы будут сделаны больше. Однако мы обнаружили, что увеличение размера канала не влияет на время выполнения. Кажется, что происходит то, что Java решает переключать потоки, даже если каналы не заполнены или пустые (т. Е. Хотя поток не должен приостанавливаться), что требует процессорного времени без видимых преимуществ. Также изменение приоритетов нитей не создает заметных различий.Необязательные переключатели контекста Java

Мой вопрос заключается в том, есть ли способ убедить Java не создавать ненужные переключатели контекста, но отключаться до тех пор, пока нет необходимости переключать потоки - есть ли способ изменить логику диспетчеризации Java? Или это реагирует на то, на что я не обращал внимания ?! Или существуют другие механизмы асинхронизма, например. Заводы, Runnable (s), возможно, даже демоны (!). Ответ кажется неочевидным, так как до сих пор ни один из моих корреспондентов не получил ответа (включая последние два профессора CS). Или, может быть, мне не хватает чего-то настолько очевидного, что люди не могут себе представить, что я этого не знаю ...

Я добавил код отправки и получения здесь - не очень элегантный, но, похоже, он работает ... ;-) В случае, если вам интересно, я думал, что логика goLock в «send» может вызвать проблему, но ее удаление временно не имеет никакого значения. Я добавил код для отправки и приема ...

public synchronized Packet receive() {

if (isDrained()) { 
    return null; 
} 

while (isEmpty()) { 


    try { 
    wait(); 
    } catch (InterruptedException e) {   
    close(); 
    return null; 

    }  

    if (isDrained()) { 

    return null; 
    } 

} 

if (isDrained()) {  
    return null; 
} 
if (isFull()) { 
    notifyAll(); // notify other components waiting to send 
} 
Packet packet = array[receivePtr]; 
array[receivePtr] = null; 
receivePtr = (receivePtr + 1) % array.length; 
//notifyAll(); // only needed if it was full 
usedSlots--; 

packet.setOwner(receiver); 

if (null == packet.getContent()) { 
    traceFuncs("Received null packet"); 
} else { 
    traceFuncs("Received: " + packet.toString()); 
} 


return packet; 

}

synchronized boolean send(final Packet packet, final OutputPort op) {

sender = op.sender; 

if (isClosed()) { 

    return false; 
} 

while (isFull()) { 


    try { 
    wait(); 
    } catch (InterruptedException e) {   
    indicateOneSenderClosed();  
    return false; 
    } 

    sender = op.sender; 

} 

if (isClosed()) { 

    return false; 
} 

try { 
    receiver.goLock.lockInterruptibly(); 
} catch (InterruptedException ex) { 
    return false; 
} 

try { 
    packet.clearOwner(); 
    array[sendPtr] = packet; 
    sendPtr = (sendPtr + 1) % array.length; 
    usedSlots++; // move this to here 
    if (receiver.getStatus() == StatusValues.DORMANT || receiver.getStatus() == StatusValues.NOT_STARTED) { 
    receiver.activate(); // start or wake up if necessary 
    } else { 
    notifyAll(); // notify receiver 
    // other components waiting to send to this connection may also get 
    // notified, 
    // but this is handled by while statement 
    } 

    sender = null; 
    Component.network.active = true; 
} finally { 
    receiver.goLock.unlock(); 

} 
return true; 

}


спасибо за вопрос! Я обсуждал тот же вопрос на форуме Sun, а вот мой последний пост на этом форуме:

Наша догадка сейчас является то, что этот эффект является результатом планирования логики Windows' .

Microsoft, кажется, признают, что эта область нуждается в некотором улучшении как это введение UMS - я цитирую: «UMS рекомендуется для применения с высокими требованиями к производительности, которые должны эффективно работать многие потоки одновременно на многопроцессорных или многоядерных системах . ... UMS - , доступный начиная с 64-разрядных версий Windows 7 и Windows Server 2008 R2. Эта функция недоступна в 32-разрядных версиях Windows. " Надеюсь, Java воспользуется UMS в более позднем выпуске .

Благодарим за помощь!

+0

Какой JDK вы используете? Попробуйте запустить то же самое под Linux-сервером ... если он работает лучше, это XP. – ReneS

+0

Любые новости по этому поводу? Вы нашли решение? – ReneS

+0

Не стоит ничего, что Java использует потоки ОС для JSE и JEE. Это означает, что вы находитесь на милость своей операционной системы. Для лучшего управления переключением контекста вы можете использовать операционную систему реального времени. Однако проблема может заключаться в том, что ваша ОС пытается быть честной с потоками в вашем процессе, и у вас больше потоков, чем у вас есть ядра, поэтому вам приходится их менять. Я бы предположил, что у вас меньше потоков, чем ядер, и он должен переключиться намного меньше. –

ответ

1

Я немного смущен - он вдруг мне пришло в голову во второй половине дня, что может быть, сеть которого производительность я беспокоился был слишком прост, как у меня было только два процесса эс, и два процесса OrS. Поэтому Windows, возможно, слишком старалась, чтобы сбалансировать процессоры! Поэтому я задавался вопросом, что произойдет, если я дам Windows много процессов.

Я создал две сети:

а) 50 Сформировать компоненты, питающие 50 Отброса компонентов - т.е. высокопараллельной сеть - так что 100 потоков в общем

б) 50 Генерировать компоненты, питающих 1 Отклонить компонент - т.е. очень «вороненая» сеть - так что это 51 поток

Я работал каждый раз 6 раз с пропускной способностью 10 и 6 раз с пропускной способностью 100. Каждый прогон генерировал в общей сложности 50 * 20 000 информационных пакетов для в общей сложности 1 000 000 пакетов, и продолжалось около 1 минуты.

Ниже представлены средние показатели по 4 шкалам: a) с мощностью подключения 10 - 59,171 сек. a) с пропускной способностью 100 - 52,008 сек.

b) с пропускной способностью 10 - 76,745 с. b) с пропускной способностью 100 - 60,667 секунд.

Таким образом, похоже, что емкость подключения действительно имеет значение! И, похоже, JavaFBP работает достаточно хорошо ... Я прошу прощения за то, что вы немного поспешны, но, возможно, это заставило нас всех подумать немного глубже о многопоточности в многоядерной машине ... ;-)

Опровергает еще раз, и спасибо всем, кто поделился мыслями по этой теме!

0

Извините, если это общий подделка, но я уверен, что Java не делает зеленые темы больше с Java 1.1. По крайней мере, Wikipedia так говорит.

Это ограничит вас использованием приоритетов, но в большинстве случаев я также не смог добиться заметных улучшений производительности.

+0

Нет, я согласен - я не добился такого прогресса! Есть ли альтернатива приоритетам? –

4

Зеленые нити исчезли (возможно, Solaris поддерживает это, но я сомневаюсь в этом). Кроме того, Java не переключает потоки, ОС делает это. Единственное, что делает Java, это сигнализация ОС, что поток не работает/ждет/блокирует с помощью функций ОС. Поэтому, если ваша программа попадает в любую точку синхронизации, Thread.wait/sleep, она будет сигнализировать, что ей больше не нужен процессор.

Кроме того, ОС поддерживает временные фрагменты и отбирает процессор из потока, даже если он все еще может работать, когда другие потоки ждут процессора.

Можете ли вы опубликовать здесь еще несколько кодов?

+0

Просто забыл упомянуть, что получение памяти всегда моментом, когда ОС может вытолкнуть поток из процессора ... – ReneS

+0

Есть ли способ увеличить длину срезов времени ОС? –

+0

Да, зависит от вашей ОС и того, в каком режиме она работает. Например, сервер Ubuntu работает с другими срезами, чем Ubuntu Desktop. (спросите у severfault.com). Но сначала попробуйте связать процесс с одним процессором и проверьте, работает ли он лучше. – ReneS

Смежные вопросы