Каков практический предел размера одного пакета, передаваемого через доменный сокет?

предположим, что существует доменный сокет Unix, созданный для типичной серверно-клиентской программы. Клиент отправляет буфер 10GB через сокет, и он потребляется сервером в то же время.

разделяет ли OS (Linux/BSD) буфер 10GB на множество пакетов и отправляет/потребляет их, или они отправляются сразу?

Если невозможно отправить буфер 10Gb сокета домена за один раз, то каков практический предел размера одного пакет?

ограничения:

  • программа будет работать как на Linux 2.6.32+, так и на FreeBSD 9+
  • размер буфера для отправки колеблется от 3 байт до 10 Гб максимум.

4 ответов


существует ряд факторов, которые будут определять максимальный размер пакета, который может быть отправлен в сокете Unix:

  1. на wmem_max socket send buffer максимальный размер ядра, который определяет максимальный размер буфера отправки, который может быть установлен с помощью setsockopt (SO_SNDBUF). Текущую настройку можно прочитать из /proc/sys/net/core/wmem_max и может быть установлен с помощью sysctl net.core.wmem_max=VALUE (добавить параметр /etc/sysctl.conf чтобы сделать изменение постоянным при перезагрузке). Примечание этот параметр применяется ко всем сокеты и протоколы сокетов, а не только сокеты Unix.

  2. если несколько пакетов отправляются в сокет Unix (используя SOCK_DATAGRAM), то максимальный объем данных, который может быть отправлен без блокировки, зависит как от размера буфера отправки сокета (см. выше)и максимальное количество непрочитанных пакетов в сокете Unix (параметр ядра net.unix.max_dgram_qlen).

  3. наконец, пакет (SOCK_DATAGRAM) требует непрерывной памяти (как Пер каков максимальный размер сообщения дейтаграммы AF_UNIX, которое может быть отправлено в linux?). Сколько оперативной памяти доступно в ядре будет зависеть от многих факторов (например, ввода/вывода нагрузки на систему и т. д...).

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

фактические цифры будут зависеть от конфигурации системы и использования. Вам нужно будет определить пределы путем тестирования... начните говорить с wmem_max на 256Kb и max_dgram_qlen в 32 и продолжайте удвоение wmem_max пока вы не заметите, что вещи начинают ломаться. Вам нужно будет настроить max_dgram_qlen чтобы сбалансировать активность производителя и потребителя в определенной степени (хотя, если производитель намного быстрее или намного медленнее, чем потребитель, размер очереди не будет иметь большого влияния).

обратите внимание, что ваш производитель должен будет специально настроить размер буфера отправки сокета в wmem_max байты с вызовом setsockopt (SO_SNDBUF) и придется разделить данные на wmem_max байтовые куски (и потребителю придется их собрать).

Best guess: практические пределы будут будьте вокруг wmem_max ~8Mb и unix_dgram_qlen ~32.


нет никаких "пакетов" за сокеты. Семантика tcp - " потоков "или udp - "датаграмм" - это своего рода имитация ядра, чтобы выглядеть похожими на приложения пользовательского пространства, но это примерно так. Механики не так задействованы, как сетевые сокеты, использующие сетевые протоколы. Что вас действительно интересует, так это то, сколько ядро будет буферизировать для вас.

С точки зрения вашей программы это не имеет значения. Думайте о гнезде как труба или FIFO. Когда буфер заполняется, вы собираетесь блокировать; если сокет не блокируется, вы получите короткие записи (предполагая потоки) или ошибку с EAGAIN. Это верно независимо от размера буфера. Однако вы должны иметь возможность запросить размер буфера с помощью getsockopt и увеличить его размер с setsockopt но я сомневаюсь, что вы собираетесь получить где-нибудь около 10GB.

кроме того, вы можете посмотреть sendfile.


здесь есть две идеи. Один-это размер пакета, отправленного при использовании SOCK_DGRAM, а другой - размер буфера для сокета домена. Это зависит от переменных, заданных с помощью сокета домена. Размер может зависеть, если это файловый сокет памяти.


Если вы говорите о SOCK_DGRAM, это легко определяется экспериментально. Кажется гораздо более вероятным, что вы говорите о SOCK_STREAM, и в этом случае это просто не имеет значения. SOCK_STREAM отсортирует его вне вас. Просто напишите в любом размере куски вам нравится: чем больше, тем лучше.