Чтение из сокета на 1 байт за раз по сравнению с чтением большим фрагментом

StackOverflow https://stackoverflow.com/questions/931713

  •  06-09-2019
  •  | 
  •  

Вопрос

В чем разница - с точки зрения производительности - между чтением из сокета по 1 байту за раз и чтением большим фрагментом?

У меня есть приложение на C ++, которому необходимо извлекать страницы с веб-сервера и анализировать полученную страницу построчно.В настоящее время я читаю по 1 байту за раз, пока не столкнусь с CRLF или не будет достигнуто максимальное значение в 1024 байта.

При чтении большим фрагментом (например,1024 байта за раз) намного лучше с точки зрения производительности, любая идея о том, как добиться того же поведения, которое у меня есть в данный момент (т.Е.возможность сохранять и обрабатывать по 1 строке html за раз - до CRLF, еще не используя последующие байты)?

Редактировать:

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

Спасибо.

Это было полезно?

Решение

Если вы читаете непосредственно из сокета, а не из промежуточного представления более высокого уровня, которое может быть буферизовано, то, без каких-либо возможных сомнений, просто лучше полностью прочитать 1024 байта, поместить их в ОЗУ в буфер, а затем проанализировать данные из ОЗУ.

Почему?Чтение в сокете - это системный вызов, и он вызывает переключение контекста при каждом чтении, что является дорогостоящим.Читайте об этом подробнее: Техническая библиотека IBM:Повысьте производительность розетки

Другие советы

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

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

Первый и самый простой:

cin.getline(buffer,1024);

Во-вторых, обычно весь ввод-вывод буферизован, так что вам не нужно слишком беспокоиться

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

Добрый день,

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

Захват одного большого куска, обычно размером до MTU, значительно эффективнее.

Почему бы не отсканировать содержимое в вектор и выполнить итерацию по нему, ища , чтобы разделить ваш ввод на строки веб-ввода?

HTH

ваше здоровье,

Вы не считываете по одному байту за раз из сокета, вы считываете по одному байту за раз из системы ввода-вывода C / C ++, которая, если вы используете CGI, уже полностью буферизовала все входные данные из сокета.Весь смысл буферизованного ввода-вывода заключается в том, чтобы сделать данные доступными программисту способом, удобным для его обработки, поэтому, если вы хотите обрабатывать по одному байту за раз, продолжайте.

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

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

Если вы привязаны к небольшому буферу, то используйте классические алгоритмы буферизации, такие как:

getbyte:
   if buffer is empty
      fill buffer
      set buffer pointer to start of buffer
   end
   get byte at buffer pointer
   increment pointer

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top