【问题标题】:Low-latency read of UDP portUDP端口的低延迟读取
【发布时间】:2012-01-14 02:09:59
【问题描述】:

我正在从 UDP 端口读取单个数据项。此读取必须是尽可能低的延迟。目前我正在通过 boost::asio 库的 async_receive_from 方法阅读。有谁知道我在到达网卡的数据包和在我的用户代码中调用的回调方法之间会遇到什么样的延迟?

Boost 是一个很好的库,但是很通用,有没有更低延迟的替代方案?

非常欢迎所有关于编写低延迟 UDP 网络程序的意见。

编辑:另一个问题,是否有一种相对可行的方法来估计我在 NIC 和用户模式之间遇到的延迟?

【问题讨论】:

  • @javapowered 是否有任何内容未包含在相应的手册页中? linux.die.net/man/7/epolllinux.die.net/man/2/recvmsg?
  • @sehe 我想我现在应该改变我的问题 :) 我决定使用普通阻塞 recvmsg 因为它在“单线程单套接字”配置中很容易并且可能还不错。接受的答案建议使用epoll(适用于许多套接字,但我们应该将它用于单个套接字吗?)。与“recvmsg one-thread one-socket”相比,它实际上会更好吗? recvmsg 屏蔽有那么糟糕吗?
  • @javapowered 一切都与选择有关。它阻塞的事实 - 在实际资源上可能会给它最低的延迟。但是公认的答案确实包含大量有关如何从您的操作系统中挤出最后一滴响应的相关信息

标签: c++ boost boost-asio latency


【解决方案1】:

您的延迟会有所不同,但远非您所能获得的最佳延迟。以下是一些阻碍您改善延迟的因素:

Boost.ASIO

  1. 它不断分配/取消分配内存来存储“状态”,以便调用与您的读取操作相关的回调函数。
  2. 它不需要mutex 锁定/解锁,以支持异步和同步方法的错误组合。
  3. 最糟糕的是,它不断地在底层通知机制中添加和删除事件描述符。

总而言之,asio 对于高级应用程序开发人员来说是一个很好的库,但它的价格很高,而且占用大量 CPU 周期。另一种选择是libevent,它要好得多,但仍旨在支持许多通知机制并独立于平台。没有什么能打败原生机制,即epoll

其他事情

  1. UDP 堆栈。对于延迟敏感的应用程序,它做得不是很好。最流行的解决方案之一是 OpenOnload。它绕过堆栈并直接与您的 NIC 一起工作。
  2. 调度程序。默认情况下,调度程序针对吞吐量而不是延迟进行了优化。您将不得不调整和调整您的操作系统,以使其面向延迟。例如,Linux 有很多用于此目的的“rt”补丁。
  3. 注意不要睡觉。一旦您的进程处于休眠状态,与不断消耗 CPU 并等待数据包到达相比,您将永远无法获得良好的唤醒延迟。
  4. 干扰其他 IRQ、进程等

我无法告诉您确切的数字,但假设您不会获得大量流量,使用 Boost 和常规 Linux 内核以及常规硬件,您的延迟将介于 ~50 微秒到 ~100 毫秒之间.随着您获得更多数据,它会有所改善,并且在某个点后开始下降,并且将始终保持测距。我想说,如果你对这些数字没意见,那就不要费心优化了。

【讨论】:

  • 这是非常好的信息,非常感谢。流量可以忽略不计,我可能会收到 1-2 个 30-50 字节的数据包,这就是整个过程的生命周期,所以我是一个极端情况。我目前在 Windows 上,但我们似乎应该在短期内转向 Linux,我会调查你提到的 RT 补丁。
  • @endian:不客气。 Linux 可能会让你做得更好。我从来没有听说过 Windows 做低延迟的工作。另外,请确保首先优化硬件。获得 Solarflare NIC 和高端服务器比优化代码便宜得多,只有在硬件支出达到合理限制时才改进代码。
  • UDT (udt.sourceforge.net) 可能值得一看,尽管它针对吞吐量进行了优化。但也许作为一个比较,它可能会很有趣......
  • 只是补充 Vlad 的答案:如果没有硬件加速,您最好的选择可能是 非阻塞 UDP 套接字上的普通 recv()
  • 只是添加一个数据点,我发现使用 boost 的延迟要低得多:大约 10 个麦克风,包括我的数据包处理代码。但是,我使用的是 64 位 linux,使用的是非常高端的服务器。不过,我得到了很大的延迟峰值,更令人担忧的是,UDP 缓冲区溢出。我感觉原生 epoll 会大大地解决问题。
【解决方案2】:

我认为在“自旋”循环线程中使用 recv() 并将线程附加到单个 CPU 核心(处理器亲和力),延迟应该低于使用 select(),select() 的精度从 1 变化到 10 微秒,而在我的测试中以 1 微秒旋转循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    • 2018-11-01
    • 2013-07-10
    • 2010-12-18
    相关资源
    最近更新 更多