Thread.sleep и BufferedReader.readLine используют большинство циклов процессора на моем tcp-сервере java Зачем? - PullRequest
1 голос
/ 30 июня 2011

Добрый вечер,

Я разрабатываю tcp-сервер java для связи между клиентами.

На данный момент я загружаю тестирование разработанного сервера.

Этим утром я взял в руки профилировщик (yourkit) и начал искать проблемные места на моем сервере.

Теперь у меня 480 клиентов, отправляющих сообщения на сервер каждые 500 мсек. Сервер пересылает каждое полученное сообщение 6 клиентам.

Сервер теперь использует около 8% моего процессора при постоянной нагрузке.

Мой вопрос касается функций Java, которые используют большинство циклов ЦП.

Java-функция, которая использует большинство циклов ЦП, является странным «Thread.sleep», за которым следует «BufferedReader.readLine».

Кажется, что обе эти функции блокируют текущий поток во время ожидания чего-либо (sleep ожидает несколько мс, readline ожидает данные).

Может кто-нибудь объяснить, почему эти две функции занимают столько процессорных циклов? Мне также было интересно, есть ли альтернативные подходы, которые используют меньше циклов ЦП.

С уважением, Т. Ахайо

Ответы [ 3 ]

2 голосов
/ 30 июня 2011

sleep () и readLine () могут использовать много процессоров, так как они оба приводят к системным вызовам, которые могут переключать контекст.Также возможно, что синхронизация для этих методов не точна по этой причине (это может быть завышенная оценка)

Способ уменьшить накладные расходы на переключение контекста / sleep () состоит в том, чтобы иметь меньше потоков и избежатьПри необходимости использовать режим сна (например, использовать ScheduledExecutorServices) накладные расходы на readLine () могут быть уменьшены с помощью NIO, но это может добавить некоторую сложность.

1 голос
/ 30 июня 2011

Сон не должен быть проблемой, если только у вас не спит куча потоков в течение коротких периодов времени (100-150 мсек "коротки", когда у вас 480 потоков, выполняющих цикл, который просто спит и делает что-то тривиальное ).

Вызов readLine должен использовать почти ничего, когда он на самом деле не читает что-то, кроме как при первом вызове. Но, как вы сказали, он блокируется, и он не должен использовать заметное количество процессора, если у вас нет маленьких окон, где он блокируется. Загрузка ЦП невелика, если вы не читаете тонны данных или не вызываете метод вначале.

Итак, ваши циклы слишком тесные, и вы слишком быстро получаете слишком много сообщений, что в конечном итоге вызывает «тонны» переключения и обработки контекста. Я бы предложил использовать инфраструктуру NIO (например, Netty), если вы не достаточно удобны с NIO, чтобы использовать ее самостоятельно.

Кроме того, 8% ЦП не , что много для 480 клиентов, которые отправляют 2 сообщения в секунду.

0 голосов
/ 30 июня 2011

Вот программа, в которой sleep использует почти 100% циклов процессора, предоставленных приложению:

for (i = 0; i < bigNumber; i++){
  sleep(someTime);
}

Почему? Потому что он не использует очень много реальных циклов процессора, и из тех, что он использует, почти все они тратятся на вход и выход sleep.

Значит ли это, что это настоящая проблема? Конечно нет.

Это проблема с профилировщиками, которые смотрят только на процессорное время.

Вам необходим сэмплер, который производит выборку по времени настенных часов, а не по времени ЦП. Он должен сэмплировать стек, а не только счетчик программ. Он должен показать вам по строке кода (не по функции) долю выборок стека, содержащих эту строку.

Обычное возражение против выборки по настенным часам состоит в том, что измерения будут неточными из-за разделения машины с другими процессами. Но это не имеет значения , потому что для поиска временных затрат не требуется точность измерений. Требуется точность местоположение . То, что вам нужно, - это точное расположение кода и сайты вызовов, которые находятся в стеке с нормальной долей фактического времени, что определяется выборкой из стека, не связанной с состоянием программы. Конкуренция с другими процессами не меняет долю времени, в течение которого сайты вызовов находятся в стеке, на достаточно большую величину, чтобы привести к отсутствию проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...