我正在从 UDP 端口读取单个数据项。此读取必须是尽可能低的延迟。目前我正在阅读 boost::asio 库的 async_receive_from
方法。有谁知道在到达网卡的数据包和在我的用户代码中调用的回调方法之间我会经历什么样的延迟?
Boost 是一个很好的库,但是很通用,有没有更低延迟的替代方案?
非常欢迎所有关于编写低延迟 UDP 网络程序的意见。
编辑:另一个问题,是否有一种相对可行的方法来估计我在 NIC 和用户模式之间遇到的延迟?
最佳答案
您的延迟会有所不同,但远非您所能获得的最佳延迟。以下是一些阻碍您改善延迟的因素:
Boost.ASIO
- 它不断分配/取消分配内存来存储“状态”,以便调用与您的读取操作相关的回调函数。
- 它会进行不必要的
mutex
锁定/解锁,以支持异步和同步方法的错误组合。 - 最糟糕的是,它不断地在底层通知机制中添加和删除事件描述符。
总而言之,asio
对高级应用程序开发人员来说是一个不错的库,但它的价格很高,而且占用大量 CPU 周期。另一种选择是 libevent
,它要好得多,但仍旨在支持许多通知机制并独立于平台。没有什么能打败原生机制,即 epoll
。
其他事情
- UDP 堆栈。对于延迟敏感的应用程序,它做得不是很好。最流行的解决方案之一是 OpenOnload。它绕过堆栈并直接与您的 NIC 一起工作。
- 调度器。默认情况下,调度程序针对吞吐量而不是延迟进行了优化。您将不得不调整和调整您的操作系统,以使其面向延迟。例如,Linux 有很多用于此目的的“rt”补丁。
- 注意不要 sleep 。一旦您的进程处于休眠状态,与不断消耗 CPU 并等待数据包到达相比,您将永远无法获得良好的唤醒延迟。
- 干扰其他 IRQ、进程等
我无法告诉您确切的数字,但假设您不会获得大量流量,使用 Boost 和常规 Linux 内核以及常规硬件,您的延迟将介于 ~50 微秒到 ~100 毫秒之间.随着您获得更多数据,它会有所改善,并且在某个点后开始下降,并且将始终保持测距。我想说,如果你对这些数字没意见,那就不要费心优化了。
关于c++ - UDP端口的低延迟读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8400508/