Что быстрее: несколько 'send's или использующий буферизацию?

Я играю вокруг с сокетами в C/Python и интересно, что самый эффективный путь состоит в том, чтобы отправить заголовкам со словаря Python на клиентский сокет.

Мои идеи:

  1. используйте a send призовите к каждому заголовку. Профессионалы: Никакое выделение памяти не необходимо. Недостатки: многие send вызовы - вероятно, подверженный ошибкам; управление обработкой ошибок должно быть скорее сложным
  2. используйте буфер. Профессионалы: один send вызов, намного легче проверка ошибок. Недостатки: нужен буфер :-) malloc/realloc должно быть довольно медленным и использовать (слишком) большой буфер для предотвращения realloc вызовы тратят впустую память.

Какие-либо подсказки для меня? Спасибо :-)

5
задан Jonas H. 14 April 2010 в 15:04
поделиться

3 ответа

Из-за того, как работает контроль перегрузки TCP, более эффективно отправлять данные сразу. TCP поддерживает окно, в котором указывается, сколько данных он позволит «в эфире» (отправлено, но еще не подтверждено). TCP измеряет возвращаемые подтверждения, чтобы определить, сколько данных он может иметь «в воздухе», не вызывая перегрузки (т. Е. Потери пакетов). Если из приложения поступает недостаточно данных, чтобы заполнить окно, TCP не может выполнять точные измерения, поэтому он консервативно сжимает окно.

Если у вас всего несколько небольших заголовков и ваши вызовы send выполняются быстро, операционная система обычно буферизует данные для вас и отправляет все в одном пакете. В этом случае контроль перегрузки TCP не является проблемой. Однако каждый вызов send включает переключение контекста из пользовательского режима в режим ядра, что приводит к накладным расходам ЦП. Другими словами, вам все равно лучше использовать буферизацию в вашем приложении.

Есть (по крайней мере) один случай, когда вам лучше без буферизации: когда ваш буфер медленнее, чем накладные расходы на переключение контекста. Если вы пишете сложный буфер на Python, это вполне может иметь место. Буфер, написанный на CPython, будет немного медленнее, чем точно оптимизированный буфер в ядре. Вполне возможно, что буферизация обойдется вам дороже, чем вы ее купите.

Если сомневаетесь, измерьте.

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

3
ответ дан 15 December 2019 в 06:21
поделиться

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

0
ответ дан 15 December 2019 в 06:21
поделиться

Вызов send () подразумевает обращение к ядру (той части ОС, которая напрямую связана с оборудованием). . Его удельная стоимость составляет около нескольких сотен тактов. Это безвредно, если вы не пытаетесь вызвать send () миллионы раз.

Обычно буферизация заключается в вызове send () только изредка, когда было собрано «достаточно данных».«Достаточно» не означает «все сообщение», но что-то вроде «достаточно байтов, чтобы удельная стоимость обработки ядра была невысокой». Как показывает практика, буфер размером 8 КБ (8192 байта) традиционно считается хорошим.

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

0
ответ дан 15 December 2019 в 06:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: