通过 UDP 发送大量小数据包会占用更多资源(cpu、zlib 压缩等)。我在这里读到,通过 UDP 发送一个约 65kBYTE 的大数据包可能会失败,所以我认为发送大量较小的数据包会更频繁地成功,但随之而来的是使用更多处理能力的计算开销(或者至少这就是我我假设)。问题基本上是这样的;发送最大成功数据包并将计算降至最低的最佳方案是什么?是否有在大多数情况下都有效的特定尺寸?我将 Erlang 用于服务器,将 Enet 用于客户端(用 C++ 编写)。也使用 Zlib 压缩,我向每个客户端发送相同的数据包(我猜是广播这个术语)。
4 回答
UDP payload
在大多数情况下,不会导致 ip 碎片的最大大小是
MTU size of the host handling the PDU (most of the case it will be 1500) -
size of the IP header (20 bytes) -
size of UDP header (8 bytes)
1500 MTU - 20 IP hdr - 8 UDP hdr = 1472 bytes
@EJP 谈到了534
字节,但我会将其修复为508
. 这是肯定不会导致碎片的字节数,因为主机可以设置的最小 MTU 大小是576,并且IP header max size
可以是60 bytes
(508 = 576 MTU - 60 IP - 8 UDP)
顺便说一句,我会尝试使用1472
字节,因为1500
它是一个足够标准的值。
如果您正在通过连接,请使用1492
而不是进行计算。1500
PPPoE
通过 UDP 发送大量小数据包会占用更多资源吗?
是的,一定会的!我刚刚做了一个流媒体应用程序的实验。该应用程序每秒发送 2000 帧数据,时间精确。每帧的数据有效负载为 24 字节。我使用 UDP 和sendto()将此数据发送到另一个节点上的侦听器应用程序。
我发现很有趣。这种程度的活动让我发送 CPU 崩溃了!我从大约 64% 的空闲 CPU 时间变成了大约 5%!这对我的应用程序来说是灾难性的,所以我必须解决这个问题。我决定尝试变化。
首先,我简单地注释掉了sendto()调用,以查看数据包组装开销是什么样的。CPU 时间减少了大约 1%。不错。好的...必须是sendto()调用!
然后,我做了一个快速的 fakeout 测试……我在每 10 次迭代中只调用一次sendto() API,但我将数据记录填充到之前长度的 10 倍,以模拟将一组较小记录组合成的效果较大的,发送频率较低。结果相当令人满意:CPU 命中率为 7%,而之前为 59%。看起来,至少在我的*NIX-like 系统上,发送数据包的操作成本很高,只是在进行调用的开销方面。
万一有人怀疑测试是否正常工作,我通过 Wireshark 对实际 UDP 传输的观察验证了所有结果,以确认一切正常。
结论:它使用更少的 CPU 时间来更少地发送较大的数据包,然后以更频繁的较小数据包的形式发送相同数量的数据。诚然,我不知道如果 UDP 开始破坏您过大的 UDP 数据报会发生什么……我的意思是,我不知道这会增加多少 CPU 开销。我将尝试找出(我想了解自己)并更新此答案。
534 字节。这需要在没有分段的情况下传输。当然,它仍然可以完全丢失。由于丢失数据包的重传和网络开销本身造成的开销比任何 CPU 开销都要大几个数量级。
您可能使用了错误的协议。 对于您关心传输的数据,UDP 几乎总是一个糟糕的选择。你在它上面完成了分层排序、重试和完整性逻辑,然后你就有了 TCP。