Я использую библиотеку asio (не бустер версия) для захвата входящих пакетов UDP через адаптер Ethernet 10 ГБ.
150 тыс. Пакетов в секунду — это хорошо, но я начинаю получать пропущенные пакеты, когда добираюсь до более высоких скоростей, таких как 300 тыс. Пакетов в секунду.
Я почти уверен, что узким местом является отдельная передача DMA на 300 тыс. С сетевой карты на хост-систему. Передачи не большие, всего 1400 байт на передачу, поэтому проблема с пропускной способностью не возникает.
В идеале я хотел бы механизм объединения данных из нескольких пакетов в одну передачу DMA на хост. В настоящее время я использую asio :: receive для синхронной передачи, которая дает лучшую производительность, чем async_receive.
Я пытался использовать команду получения с большим буфером или массив из нескольких буферов, но я всегда получаю одно чтение 1400 байт.
Есть ли способ обойти это?
В идеале я хотел бы прочитать несколько кратных из 1400 байтов за раз, при условии, что это не займет слишком много времени для заполнения всего.
то есть. подождите до 4 мс, а затем верните 4 х 1400 байт или просто вернитесь через 4 мс, если доступно много байт …
Я не контролирую всю сеть, поэтому я не могу форсировать гигантские кадры 🙁
Ура,
может быть, вы можете попробовать обходной путь с tcpdump, используя библиотеку libcap http://www.tcpdump.org/ и фильтрация для получения пакетов UDP
Я бы удалил asio
слой и идти прямо к металлу.
Если вы используете Linux, вы должны использовать recvmmsg (2) скорее, чем recvmsg()
или же recvfrom()
, поскольку это по крайней мере допускает возможность одновременной передачи нескольких сообщений в ядре, чего нет у других.
Если вы не можете сделать ни одну из этих вещей, вам нужно как минимум смягчить свои ожидания. recvfrom()
а также recvmsg()
и все, что лежит над ними в asio
никогда не доставит более одной дейтаграммы UDP одновременно. Вам нужно:
setsockopt()/SO_RCVBUFSIZ
и не думайте, что вы установили то, что получили: верните через getsockopt()
чтобы увидеть, ограничивает ли вас платформа каким-то образом.