使用java计算TCP往返时间
当我使用 10 gig 网络接口从一台 Solaris m/c 到另一台 Solaris m/c 进行跟踪路由时,40 字节数据包需要 0.073 毫秒。
当我用java做同样的事情时,时间要长得多。即使经过 10K 次迭代,它仍然更长。可能是什么原因?
Java: Sender (Snippet)
Socket sendingSocket = new Socket(address, RECEIVER_PORT);
sendingSocket.setTcpNoDelay(true);
OutputStream outputStream = sendingSocket.getOutputStream();
byte[] msg = new byte[64]; // assume that it is populated.
for (int i = 0; i < 10000; i++) {
long start = System.nanoTime();
outputStream.write(msg,0,64);
outputStream.flush();
inputStream.read(msg,0,64); // inputStream is initialized like outputstream
long end = System.nanoTime();
}
需要更长的时间 69 毫秒,而且它甚至不依赖于字节大小。即使我将其减少为 1 字节数组,它仍然需要 69 毫秒。有什么意见/建议吗?
其他观察: 1.OutputStream.write和flush只需要6微秒。 2. 同样在另一端TCPReceiver端接收并写回,只需要6微秒。
解决方案: 感谢大家对此问题的回复。 我发现这是由于套接字缓冲区大小:
solaris m/c 上设置的默认缓冲区大小所致。
接收缓冲区大小49152。
发送缓冲区大小7552。
我增加了套接字缓冲区大小,性能几乎与traceRoute匹配。
When i do traceroute from one solaris m/c to another using 10 gig network interface it takes 0.073 ms for 40 bytes packets.
When i do the same thing in java, the time is way longer. It is longer even after 10K iteration. What could be the reason ?
Java: Sender (Snippet)
Socket sendingSocket = new Socket(address, RECEIVER_PORT);
sendingSocket.setTcpNoDelay(true);
OutputStream outputStream = sendingSocket.getOutputStream();
byte[] msg = new byte[64]; // assume that it is populated.
for (int i = 0; i < 10000; i++) {
long start = System.nanoTime();
outputStream.write(msg,0,64);
outputStream.flush();
inputStream.read(msg,0,64); // inputStream is initialized like outputstream
long end = System.nanoTime();
}
It takes way longer 69 millis and it does not even depends upon the byte size. Even if i reduce it to say 1 byte array, it still takes 69 millis. Any comment/Suggestion ?
Other Observation:
1. OutputStream.write and flush only takes 6 micros.
2. Similarly on the other end TCPReceiver side which receives and writes back, it only takes 6 micros.
Solution:
Thank you all you responded for this query.
I found that it was due to the socket buffer size:
Default buffer size set on solaris m/c.
Received Buffer Size 49152.
Sending Buffer Size 7552.
I increased the socket buffer size and the performance almost matches traceRoute.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你不是在比较同类。 ICMP 和 TCP 是完全不同的协议。
如果您想确定延迟是否存在于您的代码、JVM、Solaris TCP 堆栈或网络中,您必须从 tcpdump/wireshark 等开始。
You are not comparing like with like. ICMP and TCP are way different protocols.
If you want to decide if the latency is in your code, the JVM, Solaris TCP stack or the network you'll have to start with tcpdump / wireshark etc.
这可能是由于多种因素造成的。对于初学者来说,建立 TCP 通道需要时间。必须在两个端点之间发送多个数据包才能建立可靠的介质。 ICMP 消息的情况并非如此,它们只是单个数据包。事实上,因为无论数据大小如何,您都看不到传输数据所需的时间存在差异,因此您可能会假设实际传输数据所需的时间(您正在谈论非常少量的数据)与建立通道所需的时间相比,无论哪种情况(在 10gig 连接上)都可以忽略不计。此外,完全有可能存在一些与您使用 Java(一种字节码语言)而不是在硬件上本机运行的语言(例如 C 或 C++)相关的开销。
This is probably due to a number of factors. For starters, establishing a TCP channel takes time. There are several packets that have to be sent between both endpoints to establish the reliable medium. That's not the case with ICMP messages, they are simply single packets. In fact, because you are seeing no difference in the time it takes to transmit the data regardless of size, then you can likely assume that the amount of time required to actually transmit the data (you're talking about a very small amount of data in either case on a 10gig connection) is negligible in comparison to the time it takes to establish the channel. Also, it is entirely possible that there is some overhead associated with the fact that you're using Java (a bytecode language) rather than something like C or C++ that runs natively on the hardware.
连接所需的时间可能约为 20 毫秒。您需要使用现有连接进行测试。
TCP 堆栈通过内核的速度非常慢。在许多机器上大约需要 50-100 us。您可以使用内核旁路驱动程序/支持来大幅减少这种情况。
The time it takes to connect can be about 20 ms. You need to test using an existing connection.
The TCP stack is quite slow going through the kernel. It takes about 50-100 us on many machines. You can reduce this sustantially using kernel bypass drivers/support.