Подтвердить что ты не робот

Низкозаходное чтение порта UDP

Я читаю один элемент данных из UDP-порта. Очень важно, чтобы это считалось наименьшей задержкой. В настоящее время я читаю через метод boost:: asio library async_receive_from. Кто-нибудь знает, какую задержку я буду испытывать между пакетом, поступающим на сетевую карту, и метод обратного вызова, вызываемый в моем коде пользователя?

Boost - очень хорошая библиотека, но довольно общая, есть ли альтернатива с меньшей задержкой?

Все мнения о написании низкоуровневых сетевых программ UDP приветствуются.

EDIT: Еще один вопрос: существует ли относительно возможный способ оценить задержку, которую я испытываю между NIC и пользовательским режимом?

4b9b3361

Ответ 1

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

Boost.Asio

  • Он постоянно выделяет/освобождает память для хранения "состояния", чтобы вызвать функцию обратного вызова, связанную с вашей операцией чтения.
  • Он делает ненужную mutex блокировку/разблокировку, чтобы поддерживать разбитое сочетание асинхронных и синхронизирующих подходов.
  • Хуже всего, он постоянно добавляет и удаляет дескрипторы событий из основного механизма уведомления.

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

Другие вещи

  • UDP-стек. Это не очень хорошая работа для чувствительных к задержкам приложений. Одним из самых популярных решений является OpenOnload. Он обходит стек и работает непосредственно с вашей сетевой адаптером.
  • Планировщик. По умолчанию планировщик оптимизирован для пропускной способности, а не для латентности. Вам нужно будет настроить и настроить свою ОС, чтобы сделать ее ориентированной на латентность. Linux, например, имеет множество "rt" патчей для этой цели.
  • Следите, чтобы не спать. Как только ваш процесс будет спать, вы никогда не получите хорошую латентность пробуждения по сравнению с постоянно сжиганием процессора и ожиданием поступления пакета.
  • Взаимодействие с другими IRQ, процессами и т.д.

Я не могу сказать вам точные цифры, но, полагая, что вы не будете получать много трафика, используя Boost и обычное ядро ​​Linux, с обычным оборудованием, ваша латентность будет находиться где-то между ~ 50 микросекундами и ~ 100 миллисекундами, Это немного улучшится по мере того, как вы получите больше данных, и после некоторого момента начала падения и всегда будет варьироваться. Я бы сказал, что если вы в порядке с этими номерами, не беспокойтесь о оптимизации.

Ответ 2

Я думаю, используя recv() в потоке цикла "spin" и присоединяю поток к одному ядру центрального процессора (Affinity) процессора, латентность должна быть ниже, чем при использовании select(), точность select() варьируется от 1 до 10 микросекунд, в то время как спиновая петля на 1 микросекунде в моем тесте.