Каково реальное влияние вызова socket.recv с размером bufsize, который не является степенью 2? - PullRequest
30 голосов
/ 15 июня 2011

Чтобы прочитать данные из сокета в python, вы вызываете socket.recv, который имеет эту подпись:

socket.recv(bufsize[, flags])

Документы pythonдля socket.recv смутно указать:

Примечание: Для лучшего соответствия с аппаратными и сетевыми реалиями значение bufsize должно быть относительно небольшим, равным 2, дляНапример, 4096.

Вопрос : Что значит « лучше всего соответствует аппаратным и сетевым реалиям »?Каково фактическое влияние установки размера буфера на не-двойную степень?

Я видел много другое рекомендации , чтобы сделать это чтение степенью 2. Я также хорошо знаю причины, когда часто бывает полезно иметь длины массива в виде степеней двух (операции сдвига / маскирования по длине, оптимальный размер массива FFT и т. д.), но это зависит от приложения.Я просто не вижу общей причины для этого с socket.recv.Конечно, это не относится к конкретной рекомендации в документации по python.Я также не вижу какой-либо степени оптимизации двух в базовом коде Python , чтобы сделать его специфичной для Python рекомендации

Например ... если у вас есть протокол, гдеДлина входящего пакета точно известна, очевидно, что предпочтительнее читать «максимум» только то, что нужно для пакета, с которым вы имеете дело, в противном случае вы могли бы съесть следующий пакет, и это было бы раздражающим.Если пакет, который я сейчас обрабатываю, имеет только 42 байта в ожидании, я только собираюсь установить для bufsize значение 42.

Чего мне не хватает?Когда мне приходится выбирать произвольный размер буфера / массива, я обычно (всегда?) Делаю длину степенью двойки, на всякий случай.Это просто привычка, выработанная за многие годыЯвляются ли документы по питону просто жертвой привычки?

Это не только для python, но, поскольку я специально ссылаюсь на документы по питону, я обозначу его так.


ОБНОВЛЕНИЕ : Я только что проверил размер буфера на уровне ядра в моей системе (или, по крайней мере, я думаю, что сделал ... Я сделал cat /proc/sys/net/core/rmem_default), и это было 124928. Не мощностьиз двух.rmem_max было 131071, что также явно не является степенью двойки.

Рассматривая это больше, я действительно не вижу никакой выгоды в силе двух рекомендаций.Я готов назвать это фиктивной рекомендацией ...

Я также добавил теги tcp и C, поскольку они также актуальны.

Ответы [ 2 ]

6 голосов
/ 03 октября 2017

Я почти уверен, что совет «сила 2» основан на ошибке при редактировании и не должен восприниматься как требование .

Этот конкретный совет был добавлено в документацию по Python 2.5 перенесено в документы Python 2.4.3 ) в ответ на выпуск Python # 756104 .Репортер использовал неоправданно большой размер буфера для socket.recv(), что вызвало обновление.

Это был Тим Питерс, который ввел понятие «сила 2»:

Я ожидаюВы единственный человек в истории, который попытался передать такое большое значение в recv () - даже если бы это работало, вам почти наверняка не хватило бы памяти, пытаясь выделить буферное пространство для 1,9 ГБ.сокеты - это средство низкого уровня, и принято передавать относительно небольшую степень 2 (для лучшего соответствия аппаратным и сетевым реалиям).

(выделение жирным шрифтом),Я работал с Тимом, и у него огромный опыт работы с сетевым программированием и аппаратным обеспечением, поэтому, вообще говоря, я бы взял его слово, когда делал такое замечание.Он особенно любил стек Windows 95, он назвал его своей канарейкой в ​​шахте за ее способность терпеть неудачу при стрессе.Но обратите внимание, что он говорит, что обычно , а не требуется для использования мощности 2.

Эта формулировка привела к обновлению документации:

Это ошибка документации;что-то, о чем пользователь должен быть «предупрежден».

Это поймало меня однажды, и два разных человека спросили об этом в #python, так что, возможно, мы должны добавить что-то вроде следующего в документацию по recv ().

"" "*
Для лучшего соответствия с аппаратными и сетевыми реалиями значение «буфера»
должно быть относительно небольшим: 2,
, например, 4096.
"" "

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

Никто не оспаривал здесь утверждение о степени 2, но редактор отошел от itобычно от до должно быть в промежутке нескольких ответов.

Для меня, те, кто предлагал обновление документации, были более заинтересованы в том, чтобы убедиться, что вы используете небольшой буфер , а не то, является ли это степенью 2. Это не значит, что это нехорошо совет однако;Любой низкоуровневый буфер, который взаимодействует с ядром, выигрывает от выравнивания со структурами данных ядра.

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

3 голосов
/ 16 июня 2011

В отношении: «если у вас есть протокол, в котором длина входящего пакета точно известна, очевидно, что предпочтительнее читать« максимум »то, что необходимо для пакета, с которым вы имеете дело, иначе вы могли бы потенциально съестьследующий пакет, и это будет раздражать. "

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

Тем не менее, учитывая скорость современных процессоров и объем доступной памяти, это может не быть проблемой для большинства приложений, ноэто была общая рекомендация для сетевых приложений еще в «старые времена».

Я не уверен насчет силы рекомендации 2 для приложения из пользовательского пространства.Я видел требования к этим типам для драйверов из-за проблем с выравниванием и размером страницы и т. Д., Но неясно, как это влияет на пространство пользователя, если только это не помогает копировать данные из буферов ядра в пользовательские буферы.Возможно, кто-то с большим знанием разработки ОС мог бы прокомментировать.

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