Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java套接字性能瓶颈:在哪里?_Java_Sockets - Fatal编程技术网

Java套接字性能瓶颈:在哪里?

Java套接字性能瓶颈:在哪里?,java,sockets,Java,Sockets,我最近开始开发一个应用程序,充分利用网络。 第一次尝试使用RMI,出于几个原因,我们切换到纯套接字。然而,当在网络上,甚至在本地主机上测试套接字时,我们将速率降至每秒25个请求。而使用RMI则高出两个数量级 通过进一步的测试,我们获得了以下结果(对于localhost): 始终发送相同的对象:31628个请求/秒 始终发送新对象:25个请求/秒 仅对象创建速率:每秒300-400万(因此这不是瓶颈) 以下是客户端代码:(服务器端只回复一个“ACK”) 与: 性能再次正常(几乎与相同对象情况下

我最近开始开发一个应用程序,充分利用网络。 第一次尝试使用RMI,出于几个原因,我们切换到纯套接字。然而,当在网络上,甚至在本地主机上测试套接字时,我们将速率降至每秒25个请求。而使用RMI则高出两个数量级

通过进一步的测试,我们获得了以下结果(对于localhost):

  • 始终发送相同的对象:31628个请求/秒
  • 始终发送新对象:25个请求/秒
  • 仅对象创建速率:每秒300-400万(因此这不是瓶颈)
以下是客户端代码:(服务器端只回复一个“ACK”)

与:

性能再次正常(几乎与相同对象情况下的高吞吐量相同)

发现它:

而不是:

out = new ObjectOutputStream(kkSocket.getOutputStream());
你应使用:

out = new ObjectOutputStream(new BufferedOutputStream(kkSocket.getOutputStream()));

发送消息时


…产生了巨大的变化…尽管我不知道确切的原因。

我不相信基准测试的结果。它不能确保JVM已预热;i、 e.在测量执行时间之前,类被加载、初始化并编译为本机代码。本机代码编译很有可能在一定程度上通过运行基准测试发挥作用,这会增加一个或多个循环所花费的时间。

您遇到的问题不是套接字的吞吐量低;这是缓慢的默认Java序列化

当您一遍又一遍地发送同一个对象时,它实际上只被序列化一次,然后每次都发送对它的引用;这就解释了为什么它进展如此之快

每次创建新对象时,必须使用相对较慢的Java序列化机制对新对象进行序列化,这可能比您需要的要复杂得多

要改进这一点,您可以为类实现自定义序列化代码,或者创建自己的类外部对象序列化协议(并使用DataOutput而不是ObjectOutputStream)

这篇文章有很多好的信息,即使它有点过时:
请参阅关于性能注意事项的最后一部分

处理小数据包时,应设置
TCP\u节点延迟
选项。否则,它们将在尝试优化网络通信(也称为)时被延迟


使用缓冲区之所以有帮助,是因为延迟只影响小数据包。因此,缓冲本身并不是有帮助的,而是数据包的大小。

与此问题相同:…也没有答案。如果对象彼此不引用,则可能需要在写入后调用ObjectOutputStream.reset(),以防止流记住它写入的所有对象。虽然它通常会导致读取端的内存问题,而不是服务器端的性能问题。您是否尝试分析您的应用程序以查看它在哪里花费的时间最多?这可能是问题的一部分,但只是问题的一部分。请看我的评论,我可以解释。如果使用不使用缓冲区的流,则每次
write
都会产生一个系统调用。每个syscall的开销可能是数千条额外的机器指令。ObjectOutputStream在内部运行自己的1k缓冲区。将BufferedOutputStream添加到堆栈中并没有多大区别。问题不是“缓慢的默认Java序列化”,而是序列化对象和句柄之间的区别。仅仅重新发送同一个对象的测试实际上并没有执行任何有趣的操作,因此其结果也不感兴趣。
out = new ObjectOutputStream(new BufferedOutputStream(kkSocket.getOutputStream()))
out = new ObjectOutputStream(kkSocket.getOutputStream());
out = new ObjectOutputStream(new BufferedOutputStream(kkSocket.getOutputStream()));
out.flush();
    socket.setTcpNoDelay(true);