我正在构建一个简单的Java网络应用程序,但是我遇到了性能问题。
该应用程序非常简单,包含2个部分(source code):
我正在尝试发送大量小数据,但最大发送速率为每秒50个包裹。
因此,在我的搜索中,我发现this question遇到了同样的问题。
当我将Buffered流添加到输出流时,速率变大(千位每秒)
在wireshark中,我可以很好地看到区别:
我也发现与此相关的question并没有帮助。
为什么简单的代码行如此不同?
为什么Java中的简单解决方案这么慢?
答案 0 :(得分:0)
历史上,套接字是使用启用的Nagle's algorithm打开的,这会延迟小数据包以优化网络通信。
在处理小数据包时,应设置TCP_NODELAY
套接字选项。在Java中,您可以通过调用socket.setTcpNoDelay(true);
调整后,我得到:
我调整后的代码:
public class Test {
static DataOutputStream cout(Socket s) throws IOException {
return new DataOutputStream( (s.getOutputStream()));
// return new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
}
static DataInputStream cin(Socket s) throws IOException {
return new DataInputStream( (s.getInputStream()));
}
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket server = new ServerSocket(12345);
new Thread(() -> {
try {
Thread.sleep(1000);
Socket client = new Socket("127.0.0.1", 12345);
client.setTcpNoDelay(true);
DataOutputStream out = cout(client);
DataInputStream in = cin(client);
long tm1 = System.currentTimeMillis();
int lastCount = 0;
for (int i=0;i<300000;i++) {
int a = in.readInt();
out.writeInt(a);
out.flush();
long tm2 = System.currentTimeMillis();
if ((tm2 - tm1) >= 1000) {
System.out.println(i - lastCount);
lastCount = i;
tm1 += 1000;
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}).start();
Socket client=server.accept();
client.setTcpNoDelay(true);
DataOutputStream out = cout(client);
DataInputStream in = cin(client);
for (int i=0;i<300000;i++){
out.writeInt(i);
out.flush();
if (i!=in.readInt()){
System.out.println("ERROR");
}
}
client.close();
server.close();
Thread.sleep(1000);
}
}