【问题标题】:Will UDP socket pool improve datagram delivery successful rate and be more efficient?UDP套接字池会提高数据报投递成功率,效率更高吗?
【发布时间】:2014-04-16 08:11:25
【问题描述】:

我正在使用 C 在 Solaris 中开发一个 UDP 客户端模块,有 2 个设计模块:

(1) 创建一个socket,通过这个socket发送所有的消息。接收线程仅在此套接字上调用recvfrom

(2) 创建一组套接字。发送消息时,从套接字池中随机选择一个套接字。接收线程需要在一组套接字上调用pollselect

当吞吐量较低时,我认为第一个设计模块是可以的。

如果吞吐量高,我想知道第二个设计模块是否可以更好? 因为它会将消息分发到一组套接字,这样可能会提高UDP数据报传递的成功率和效率。

【问题讨论】:

  • 您期望的吞吐量是多少?运行速度是 10Mb、100Mb、1Gb、10Gb 还是 100Gb?此外,您的服务器有什么 CPU 和架构?有多少个核心,核心有多快?我想回答,但这很大程度上取决于这些问题。

标签: c sockets unix udp solaris


【解决方案1】:

仍然只有一个网络。您可以拥有任意数量的套接字、线程等。速率确定步骤是网络。这没有任何意义。

【讨论】:

    【解决方案2】:

    这里的问题主要取决于计算机的并行程度(内核数量)以及算法的并行程度。无论如何,您的 CPU 内核很可能比网络连接快得多,即使其中一个内核也很容易使连接不堪重负。因此,在典型系统上,选项 (1) 将提供明显更好的性能和更低的丢弃率。

    这是因为在多个线程或进程上使用 UDP 端口会产生很大的开销,因为操作系统必须执行内部锁定以确保数据包的内容不会被多路复用和损坏,这会导致显着的性能损失和当内核放弃等待其他线程而只是将待处理的数据包丢弃时,丢包的机会显着增加。

    在您的内核非常慢且连接速度非常快的极端情况下(例如,具有 10 - 100Gbit 光纤连接的 500 核超级计算机)选项二可能会变得更可行,锁定的可能性较小,因为连接会足够快以使许多内核保持忙碌而不会相互绊倒并经常锁定,这不会增加可靠性(并且可能会稍微降低它),但可能会增加吞吐量,具体取决于您的架构。

    总的来说,在几乎所有情况下,我都会建议选项 1,但如果您确实遇到了极高的吞吐量情况,您应该考虑其他方法,但是如果您正在为这种系统编写软件,您可能会受益于一些更通用的方法在大规模并行系统中进行训练。

    希望对你有帮助,如有疑问请留言。

    【讨论】:

    • 从什么时候开始内核“放弃等待其他线程并丢弃您的 outbound 数据包”?
    • @EJP 诚然,我还没有查看 Solaris 的源代码,因此无法告诉您它将做什么,但这绝对符合要求,如果内核可以在 BSD 样式的套接字实现中丢弃 UDP 数据包,则网络接口太忙而无法处理它们,否则在 CPU 发送数据包的速度快于网络接口传输它们的速度的情况下,内核将需要一个无限的待处理数据包队列。 (当然也可以让进程阻塞,但是这对于操作系统来说更难预测,所以经常使用丢弃的方法。)
    • 谁投了反对票,请给我机会在投票前解释或编辑我的答案,否则我无法帮助解决您的疑虑,也不知道答案有什么问题。
    • @EJP 例如,看看 Linux 内核的 UDP 多播支持,在某些情况下可以丢弃出站 UDP 数据包。此外,如果内核对 UDP 使用速率限制,这是一个可用且经常使用的选项,也会导致它有时会丢弃 UDP 数据包。
    • 内核对每个 TCP 或 UDP 套接字都有一个套接字发送缓冲区,其大小由套接字选项 SO_SNDBUF 给出,并且它能够在发送方已满时阻塞发送方。当套接字发送缓冲区已满时,send() 仅有的两种允许行为是 (1) 阻塞或 (2) 在非阻塞模式下返回 -1/EAGAIN。
    猜你喜欢
    • 2014-10-09
    • 2017-06-17
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多