使用ASIO抓取大量UDP包
Using ASIO to capture lots of UDP packets
我正在使用 asio(非 boost 版本)库通过 10GB 以太网适配器捕获传入的 UDP 数据包。
每秒 150k 个数据包很好,但是当我达到 300k packets/sec.
等更高速率时,我开始丢失数据包
我很确定瓶颈在于从网卡到主机系统的 DMA'ing 300k 单独传输。传输量不大,每次传输只有 1400 字节,所以不是带宽问题。
理想情况下,我希望有一种机制可以将来自多个数据包的数据合并为单个 DMA 传输到主机。目前我正在使用 asio::receive 进行同步传输,这比 async_receive 提供更好的性能。
我尝试过使用具有更大缓冲区的接收命令,或使用多个缓冲区的数组,但我似乎总是获得 1400 字节的单次读取。
有什么解决办法吗?
理想情况下,我想一次读取 1400 字节的一些倍数,只要不会花费太长时间来填充总数。
IE。最多等待 4 毫秒,然后 return 4 x 1400 字节,或者只是 return 在 4 毫秒之后,无论有多少字节可用...
我不控制整个网络,所以我不能强制使用巨型帧:(
干杯,
也许您可以尝试使用 libcap 库 http://www.tcpdump.org/ 和过滤以接收 UDP 数据包的 tcpdump 变通方法
我会移除 asio
层并直接进入金属。
如果您使用 Linux,您应该使用 recvmmsg(2) 而不是 recvmsg()
或 recvfrom()
,因为它至少允许在内核中的时间,其他人没有。
如果您做不到这两件事,您至少需要降低您的期望。 recvfrom()
和 recvmsg()
以及 asio
中位于它们之上的任何内容都不会一次传送超过一个 UDP 数据报。您需要:
- 尽可能加快接收循环,消除所有可能的开销,尤其是动态内存分配和 I/O 到其他套接字或文件。
- 通过
setsockopt()/SO_RCVBUFSIZ
确保套接字接收器缓冲区尽可能大,至少 1 兆字节,并且不要假设你设置的就是你得到的:通过 [=17 取回它=] 查看平台是否在某些方面限制了您。
我正在使用 asio(非 boost 版本)库通过 10GB 以太网适配器捕获传入的 UDP 数据包。 每秒 150k 个数据包很好,但是当我达到 300k packets/sec.
等更高速率时,我开始丢失数据包我很确定瓶颈在于从网卡到主机系统的 DMA'ing 300k 单独传输。传输量不大,每次传输只有 1400 字节,所以不是带宽问题。
理想情况下,我希望有一种机制可以将来自多个数据包的数据合并为单个 DMA 传输到主机。目前我正在使用 asio::receive 进行同步传输,这比 async_receive 提供更好的性能。
我尝试过使用具有更大缓冲区的接收命令,或使用多个缓冲区的数组,但我似乎总是获得 1400 字节的单次读取。
有什么解决办法吗?
理想情况下,我想一次读取 1400 字节的一些倍数,只要不会花费太长时间来填充总数。 IE。最多等待 4 毫秒,然后 return 4 x 1400 字节,或者只是 return 在 4 毫秒之后,无论有多少字节可用...
我不控制整个网络,所以我不能强制使用巨型帧:(
干杯,
也许您可以尝试使用 libcap 库 http://www.tcpdump.org/ 和过滤以接收 UDP 数据包的 tcpdump 变通方法
我会移除 asio
层并直接进入金属。
如果您使用 Linux,您应该使用 recvmmsg(2) 而不是 recvmsg()
或 recvfrom()
,因为它至少允许在内核中的时间,其他人没有。
如果您做不到这两件事,您至少需要降低您的期望。 recvfrom()
和 recvmsg()
以及 asio
中位于它们之上的任何内容都不会一次传送超过一个 UDP 数据报。您需要:
- 尽可能加快接收循环,消除所有可能的开销,尤其是动态内存分配和 I/O 到其他套接字或文件。
- 通过
setsockopt()/SO_RCVBUFSIZ
确保套接字接收器缓冲区尽可能大,至少 1 兆字节,并且不要假设你设置的就是你得到的:通过 [=17 取回它=] 查看平台是否在某些方面限制了您。