Java - Использование DataInputStream с сокетами, буферизованными или нет? - PullRequest
7 голосов
/ 06 ноября 2010

Я пишу простое клиент-серверное приложение и обнаружил, что использовать DataInputStream для чтения данных было очень удобно, потому что он позволяет выбирать, что читать (без необходимости конвертировать его из байтов), но мне интересноесли было бы лучше обернуть его в BufferedInputStream тоже, или если это просто добавило бы ненужные накладные расходы?

Причина, по которой я спрашиваю, заключается в том, что я не знаю, насколько дорого читать напрямую изпоток сокетов (при использовании BufferedInputStream он будет просто один раз читать из потока сокетов, а затем умножать число раз из BufferedInputStream с использованием DataInputStream).

Получаемые данные обычно довольно малы, около 20-25 байт.

Заранее спасибо за любой ответ!: D

Ответы [ 2 ]

7 голосов
/ 06 ноября 2010

DataInputStream не буферизуется, поэтому каждая операция чтения для объекта DataInputStream приведет к одному или большему числу чтений в основном потоке сокета, что может привести к нескольким системным вызовам эквивалент).

Системный вызов обычно на 2–3 порядка дороже, чем обычный вызов метода. Буферизованные потоки работают за счет уменьшения количества системных вызовов (в идеале до 1) за счет добавления дополнительного уровня регулярных вызовов методов. Обычно использование буферизованного потока заменяет N системных вызовов на 1 системный вызов и N дополнительных вызовов методов. Если N больше 1, вы выигрываете.

Из этого следует, что единственными случаями, когда BufferedInputStream между потоком сокета и DataInputStream является , а не выигрыш, являются:

  • когда приложение выполняет только один read...() вызов, и это может быть удовлетворено одним системным вызовом,
  • , когда приложение выполняет только большие read(byte[] ...) вызовы, или
  • когда приложение ничего не читает.

Похоже, они не применимы в вашем случае.

Кроме того, даже если они применяются, накладные расходы на использование BufferedInputStream, когда вам это не нужно, относительно невелики. Затраты на использование BufferedInputStream, когда вам это нужно, могут быть огромными.

И последнее замечание: фактический объем прочитанных данных (то есть размер сообщений) составляет в значительной степени не имеет отношения к для буферизованной и небуферизованной головоломки. Что действительно важно, так это способ чтения данных; то есть последовательность read...() вызовов, которые будет выполнять ваше приложение.

2 голосов
/ 06 ноября 2010

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

Вы говорите, что полученные данные обычно малы: как часто вы ожидаете большие сообщения? Это будет существенным узким местом, если вы будете время от времени получать большие сообщения в небуферизованном потоке.

Я бы посоветовал вам запустить некоторые временные тесты и посмотреть, поможет ли буферизация в вашем случае. Или не беспокойтесь о временных тестах и ​​просто используйте буфер. Если размер сообщения изменится в будущем, это уменьшит обслуживание в дальнейшем.

...