启用TCP_NODELAY的Linux Loopback性能

17

我最近在运行一些性能测试时,偶然发现了一个有趣的TCP性能问题:将网络性能与回送性能进行比较。在我的情况下,网络性能超过了回送性能(1Gig网络,同一子网)。在我所处理的情况中,延迟非常关键,因此启用了TCP_NODELAY。我们提出的最佳理论是TCP拥塞控制正在阻止数据包的传输。我们进行了一些数据包分析,可以明确地看到数据包被阻塞了,但原因并不明显。现在有几个问题:

1)在什么情况下,以及为什么,通过回送传输通信速度会比网络传输慢?

2)在尽可能快地发送数据时,为什么在回送上切换TCP_NODELAY对最大吞吐量的影响要比在网络上大得多?

3)我们如何检测和分析TCP拥塞控制作为效果差的潜在解释?

4)是否有其他理论来解释这种现象?如果是,有没有任何证明理论的方法?

以下是由一个简单的点对点C ++应用程序生成的一些示例数据:

Transport     Message Size (bytes)  TCP NoDelay   Send Buffer (bytes)   Sender Host   Receiver Host   Throughput (bytes/sec)  Message Rate (msgs/sec)
TCP           128                      开启            16777216              主机A         主机B           118085994                922546
TCP           128                      关闭            16777216              主机A         主机B           118072006                922437
TCP           128                      开启               4096              主机A         主机B            11097417                 86698
TCP           128                      关闭               4096              主机A         主机B            62441935                487827
TCP           128                      开启            16777216              主机A         主机A            20606417                160987
TCP           128                      关闭            16777216              主机A         主机A           239580949               1871726
TCP           128                      开启               4096              主机A         主机A            18053364                141041
TCP 128 关闭 4096 HostA HostA 214148304 1673033 UnixStream 128 - 16777216 HostA HostA 89215454 696995 UnixDatagram 128 - 16777216 HostA HostA 41275468 322464 NamedPipe 128 - - HostA HostA 73488749 574130

以下是更多有用的信息:

  • 我只在处理小消息时发现了这个问题
  • HostA和HostB都具有相同的硬件配置(Xeon X5550 @ 2.67GHz,总共32个核/ 128 Gig内存/ 1Gig网卡)
  • 操作系统为RHEL 5.4内核2.6.18-164.2.1.el5)

谢谢你


如果延迟非常重要,我会切换到UNIX域套接字(与TCP套接字非常相似)或管道(更快,但更复杂,需要两个管道进行双向连接)。它们比TCP套接字携带更少的负担,并提供更低的延迟。 - Peter G.
这些问题可能不相关,但我很好奇。在这两种情况下,您看到的实际结果是什么?吞吐量和时间是多少?此外,测试是大多数情况下单向发送,还是更像回声样式的测试,在响应中发送相同数量的数据? - Mark Wilkins
@Mark,我把我们测试的结果添加到了主要帖子中。我还添加了一些其他相关细节。测试是单向发送的。 - rns
感谢您发布这些信息,它确实很有趣,但并没有给我带来任何有用的想法。TCP_NODELAY启用时的差异确实非常明显(吞吐量的10%)。它几乎有一种“感觉”,即每个发送请求都会阻塞,直到收到ACK。但这并没有太多意义。 - Mark Wilkins
3个回答

9

1) 在什么情况下,为什么使用环回通信会比网络通信慢?

环回通信将数据包的设置和TCP校验和计算都放在同一台机器上进行,因此需要进行2倍的处理。而在2台机器之间,你可以将发送/接收分配在它们之间。这可能会对环回通信产生负面影响。

2) 当尽可能快地发送数据时,为什么在环回通信中切换 TCP_NODELAY 会对最大吞吐量产生比在网络通信中更大的影响?

不确定您是如何得出这个结论的,但是环回通信与网络通信的实现方式非常不同,如果您试图将它们推向极限,您将遇到不同的问题。环回接口(如答案1中所述)会在同一台机器上引起发送/接收处理开销。另一方面,NIC有许多限制,例如它们可以在其循环缓冲区中具有多少未完成的数据包等,这会导致完全不同的瓶颈(这也因芯片而异,甚至因它们之间的交换机而异)。

3) 我们如何检测和分析TCP拥塞控制作为性能不佳的潜在解释?

只有在出现数据包丢失时,拥塞控制才会启动。您是否看到数据包丢失?否则,您可能会遇到tcp窗口大小与网络延迟因素之间的限制。

4) 是否有其他理论可以解释这种现象?如果有,任何证明该理论的方法吗?

我不理解您在此处提到的现象。在您的表格中,我只看到一些具有大型发送缓冲区的套接字 - 这可能是完全合法的。在快速的机器上,您的应用程序肯定能够产生比网络所能传输的更多的数据,因此我不确定您将什么归类为问题。

最后要注意的一点是:小消息由于各种原因会对您的网络产生更大的性能影响,例如:

  • 每个数据包都有固定的开销(用于MAC + IP + TCP头),而负载越小,您将拥有更多的开销。
  • 许多NIC限制相对于未完成数据包的数量,这意味着当使用较小的数据包时,您将使用更少的数据来达到NIC瓶颈。
  • 网络本身具有每个数据包的开销,因此您可以通过数据包的大小来确定可以通过网络传输的最大数据量。

1

1或2)我不确定你为什么要使用回环,我个人不知道它会模拟真实接口多少,以及它是否有效。我知道Microsoft禁用了回环接口的NAGLE(如果您在乎的话)。看看this link,有一些相关的讨论。

3)我会仔细查看两种情况下的前几个数据包,并查看前五个数据包是否存在严重延迟。请参见here


我在“此链接”中没有看到任何关于MS禁用环回接口的Nagle的说明。该主题似乎是关于当用户这样做时会发生什么。他问:“为什么在环回上禁用Nagle算法会更糟?”,如果已经关闭,那就不会这样。你能澄清一下吗? - user207421
我们使用环回的原因是我们认为它会获得更好的性能,但现在我们遇到了这种现象,我们正在努力找出原因。此外,使用环回还有真实世界的用例(因为预计会获得更好的性能并减少硬件成本)。 - rns
那个链接与微软无关,它与问题有关,也许您可以从帖子中推断出一些东西 - 我认为它并不包含答案 - 但可能会讨论相关的想法。 - stackmate
@user207421:FYI,微软的文档 确实说明了Nagle在loopback接口上会自动禁用(在链接中搜索“loopback”):“为提高性能,Nagle算法不适用于loopback TCP连接。” - ShadowRanger

1
这是我也遇到的问题。在同一台运行RHEL6的机器上,当在两个组件之间传输2 MB的数据时,需要7秒才能完成。当数据量较大时,时间是不可接受的。传输10 MB的数据需要1分钟。
然后我尝试禁用了TCP_NODELAY。它解决了这个问题。
当两个组件在两台不同的机器上时,就不会出现这种情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接