Linux上的Socket性能

5

继上次问题之后:

使用Java对象流和套接字的性能问题

我正在研究Linux上的套接字性能。使用以上示例,我得到了约65μsec的往返时间。如果我在文件系统上创建两个FIFO,则可以将其降至约45μsec。使用本地主机套接字所需的额外时间必须是因为我正在访问网络堆栈。

是否有一些操作系统配置可以使本地主机套接字与命名管道一样快?

uname -a
Linux fiatpap1d 2.4.21-63.ELhugemem #1 SMP Wed Oct 28 23:12:58 EDT 2009 i686 athlon i386 GNU/Linux

提前感谢您!


4
你正在使用基于2.4的内核?这就是问题的一部分。 - Robert S. Barnes
是的,我也仍在使用唱片机 ;)你知道内核的后续版本是否会以不同的方式优化本地网络流量吗? - Jonathan
可能不太适合,您能解释一下为什么不适合使用命名管道吗?您尝试过使用UDP而不是TCP吗?(DatagramSocket) - Ivan
除了我的Java应用程序不再具备可移植性之外,使用命名管道没有任何问题。由于需要更强的韧性,我不太喜欢使用UDP。 - Jonathan
3个回答

2
使用上述示例,我得到了大约65微秒的往返时间。如果在文件系统上创建两个FIFO,则此时间将降至约45微秒。使用本地主机套接字所需的额外时间必须是因为我正在访问网络堆栈。
是的,这是可以预期的。
FIFO是一种相当原始的通信方法。它们的状态基本上是一个布尔变量。读取和写入通过固定大小的预分配缓冲区进行。因此,操作系统可以并且确实优化这些操作。
套接字更加复杂。它们具有完整的TCP状态机。缓冲区是动态和双向的(recv、send分别被缓冲)。这意味着当你向本地套接字写入某些内容时,几乎总会涉及某种动态内存管理。Linux尽可能避免这种情况:零拷贝/单拷贝技巧已经在各个地方实现。但显然,由于需要通过更多的代码调用,它们会更慢。
最终,考虑到套接字比FIFO要复杂得多,20微秒的差异实际上说明了Linux套接字性能的多么出色。
顺便说一下,65微秒的往返时间=一个方向上的约35微秒。1秒/ 35微秒=约30K个数据包每秒。对于没有进行优化且使用单个连接的网络代码来说,这听起来就是正确的。

1

我无法在Java方面帮助您,但您可以看一下UNIX域套接字。这里有一个问题,讨论如何在Java中使用它们:

Java的UNIX套接字实现?


是的,我可以使用基于JNI的东西。如果可能的话,我宁愿不这样做。我希望一些较新版本的Linux会为我执行此优化。 - Jonathan

1

你之前的问题有两个错误的假设:

  1. ICMP_ECHO(也称ping)可以提供有意义的时间信息。实际上并不是这样,因为ICMP层可以(而且应该)处于低服务优先级。
  2. 通过无数Java接口进行数据编组不会成为瓶颈。但事实上它确实会成为瓶颈。

你的测试方法非常可疑。你想要达到什么目的?


太棒了!回答得真好。该死的那些无数Java接口和它们的性能成本。 - Matt Joiner
  1. ping 给我的时间与使用命名管道进行测试的时间几乎相同。
  2. 你是如何得出那个结论的?
- Jonathan

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