Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Что быстрее BufferedReader.readLine() ?


Автор: Aerodron 7.4.2008, 14:19
Доброго впемени суток.

Столкнулись со следущей проблеммой: При работе сервера, он ждет пакеты от клиентов  в BufferedReader.readLine().
Это место оказалось самым узким в его работе. При этом, работа потока с readLine съедала в среднем около 98% процессорного времени. Какой альтернативный вариант можно использовать для чтения данных, который использовал бы хотябы в половину меньше процессорного времени?

Вот часть кода, которая работает с readLine() :
Код

BufferedReader input = new BufferedReader(new InputStreamReader(in), 512);
while ((null != (s = input.readLine()))) {
    if(StringWizard.stringNotEmpty(s))
        ...
}

Автор: LSD 7.4.2008, 14:23
Ну во первых зачем ты сделал такой маленький размер буфера? 

Во вторых ты уверен, что 98% процессорного времени приходится именно на метод readLine(), а не на всю обработку? 

В третих читать надо обязательно по строчно (до символа конец строки)? И каков средний размер одного пакета?

Автор: Aerodron 7.4.2008, 15:26
Пробовал размер буфера менять до 2 кБ - эффект практически незаметен. Средняя загруженность практически одинакова.

Пакеты очень разные по величине. Самый маленький 52 байт. А есть и больше 2 кБ, но они встречаются нечасто.

То что 98% процессорного времени приходится на метод readLine() посчитала тулза - YourKit Java ProFiler.
Может, я неправильно интерпретировал ее статистику. Вот на всякий случай, ее данные:

http://ipicture.ru/

А читать построчно надо потому, что все пакеты оканчиваются на символ окончания строки.

Автор: COVD 7.4.2008, 15:48
Может, измерительный инструмент показывает время ожидания, а не процессорное время. Большую часть времемени процесс ожидает данных в readLine, т.е. стоит. Если данные поступают из сети ( с базы данных, с другого компьютера) и сеть или удаленный компьютер тормозят, то при чем здесь BufferedReader?  Читайте в отдельном потоке, чтобы медленный источник данных не замораживал все приложение. 
ps. А с размером буфера не морочьте себе голову - используйте default. 

Автор: Aerodron 7.4.2008, 16:26
Цитата

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

Это именно процессорное время.

Цитата

Большую часть времемени процесс ожидает данных в readLine, т.е. стоит. 

Тогда почему в это время должен грузиться процессор даже в виндовом мониторе?

Запущено около 200 потоков, которым приходят пакеты каждые полсекунды сбъемом примерно 200 байт. Это нагрузочное тестирование сервера. Процессор загружен практически на 100%. 
Profiler показывает, что большая часть нагрузки приходится именно на этот метод - readLine().
Задача - уменьшить нагрузку на сервер.

Автор: COVD 7.4.2008, 17:29
Метод readLine использует блокирующий метод read класса Reader. Это означает, что в отсутствие данных поток должен стоять. Буферизация в BufferedReader означает, что он пытается читать "вперед" при каждом вызове readLine, т.е. если данных пришло больше чем одна строка, то он все данные прочитает в буфер, но вернет только одну строку. Никаких подводных камней здесь вроде нет. Альтернативно можно использовать NIO - тогда можно избавиться от 200 потоков.

Автор: w1nd 8.4.2008, 08:30
Цитата(Aerodron @  7.4.2008,  16:26 Найти цитируемый пост)
Это именно процессорное время.

Это не процессорное время, а время выполнения теста. Вы просто видите, что readLine() выполнялся бОльшую часть времени. На что бы вы не поменяли readLine(), картина будет такой же.

Автор: mindflyer 9.4.2008, 18:03
Хм, скорее всего, это время работы метода, т.е. с учётом ожидания. Во всяком случае, в моей практике в подобных местах (ввод/вывод) было именно так.

Автор: LSD 9.4.2008, 18:20
Цитата(mindflyer @  9.4.2008,  19:03 Найти цитируемый пост)
Хм, скорее всего, это время работы метода, т.е. с учётом ожидания. Во всяком случае, в моей практике в подобных местах (ввод/вывод) было именно так.

Ожидание на IO не потребляет процессорное время.

Автор: mindflyer 11.4.2008, 09:49
Цитата(LSD @  9.4.2008,  18:20 Найти цитируемый пост)
Ожидание на IO не потребляет процессорное время. 

Я хотел сказать, что в используемом мною профайлере (JProfiler) по-дефолту показывалось именно полное время работы метода, а не затраченное процессорное время. Вероятно, это можно настроить - не искал, не было такой надобности, но эту особенность для себя отметил.

Автор: Aerodron 22.4.2008, 10:34
Спасибо всем. Это, вероятнее всего, и есть время работы метода, а не затраченное процессорное время. 
(Интересно, каким образом можно вообще измерить процессорное время. Время ведь, скорее всего, замеряется в начале работы метода и в конце работы, а чтобы померять нагрузку на процессор... наверное нужно мерять время работы каждой комманды процессора, а это очень и очень затратно и считать их общее время в методе, что в итоге на порядок замедлит работу)
То есть, именно время работы метода тратилось на IO, но
Цитата

Ожидание на IO не потребляет процессорное время.

в итоге - просто пришлось считать нагрузку, не учитывая ReadLine.
Всем спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)