Ненужные переключатели контекста Java - PullRequest
2 голосов
/ 19 ноября 2009

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

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

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

</p> <p>public synchronized Packet receive() {</p> <pre><code>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 Сервер 2008 R2. Эта функция недоступна в 32-разрядных версиях Windows. «Будем надеяться, что в будущем Java будет использовать UMS. релиз.

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

Ответы [ 3 ]

4 голосов
/ 19 ноября 2009

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

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

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

1 голос
/ 02 декабря 2009

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

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

a) 50 генераций компонентов, питающих 50 компонентов Discard - то есть высокопараллельной сети - всего 100 потоков

b) 50 Генерация компонентов, подающих 1 компонент Discard - то есть сеть с высокой степенью «воронки», то есть 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 работает достаточно хорошо ... Я прошу прощения за то, что был немного поспешным - но, возможно, это заставило всех нас задуматься о многопоточности в многоядерной машине ...; -)

Снова извиняюсь, и спасибо всем, кто поделился своими мыслями по этой теме!

0 голосов
/ 19 ноября 2009

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

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

...