Ненужные переключатели контекста Java

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

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

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

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;

}

синхронизированная логическая отправка (последний пакет пакетов, окончательная операция OutputPort) {

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.

Спасибо за вашу помощь!


person Paul Morrison    schedule 18.11.2009    source источник
comment
Какой JDK вы используете? Попробуйте запустить то же самое под Linux-сервером... если он работает лучше, это XP.   -  person ReneS    schedule 19.11.2009
comment
Есть новости по этому поводу? Вы нашли решение?   -  person ReneS    schedule 23.11.2009
comment
Ничего не стоит, что Java использует потоки ОС для JSE и JEE. Это означает, что вы зависите от того, как работает ваша ОС. Для лучшего контроля переключения контекста вы можете использовать операционную систему реального времени. Однако проблема может заключаться в том, что ваша ОС пытается быть справедливым по отношению к потокам в вашем процессе, и у вас больше потоков, чем ядер, поэтому ей приходится их менять местами. Я бы посоветовал вам иметь меньше потоков, чем ядер, и он должен переключаться гораздо реже.   -  person Peter Lawrey    schedule 12.05.2010


Ответы (3)


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

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

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

person ReneS    schedule 19.11.2009
comment
Просто забыл упомянуть, что получение памяти - это всегда момент, когда ОС может оттолкнуть ваш поток от процессора... - person ReneS; 19.11.2009
comment
Есть ли способ увеличить длину временных отрезков ОС? - person Paul Morrison; 19.11.2009
comment
Да, зависит от вашей ОС и режима, в котором она работает. Например, на сервере Ubuntu работают другие слайсы, а не Ubuntu Desktop. (спросите на severfault.com). Но попробуйте сначала привязать свой процесс к одному процессору и проверьте, работает ли он лучше. - person ReneS; 19.11.2009

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

Я настроил две сети:

а) 50 Генерировать компоненты, подающие 50 Отбрасывать компоненты — т. е. высокопараллельную сеть — так что всего 100 потоков

б) 50 Генерировать компоненты, подающие 1 Отбрасываемый компонент — т. е. сильно «воронкообразную» сеть — так что это 51 поток

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

Вот средние значения для 4-х случаев: а) с пропускной способностью 10 - 59,151 сек. а) при пропускной способности соединения 100 - 52,008 сек.

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

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

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

person Paul Morrison    schedule 02.12.2009

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

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

person Marcel Jackwerth    schedule 19.11.2009
comment
Нет, я согласен - я не добился никакого прогресса таким образом! Есть ли альтернатива приоритетам? - person Paul Morrison; 19.11.2009