本地主机上java套接字性能缓慢

33qvvth1  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(246)

我正在构建一个简单的java网络应用程序,我遇到了一个性能问题。
该应用程序非常简单,包含两部分(源代码):
作为主线程的服务器。
客户端是由main启动的新线程。
我试图发送大量的小数据,但最大发送速率是每秒50包。
所以在我的研究中,我发现这个问题和同样的问题。
当我将缓冲流添加到输出流时,速率会变大(每秒千次)
在wireshark中,我可以很清楚地看到不同之处:
在慢运行时有push标志,在不同的包中有ack标志,有的ack甚至可以达到45毫秒的延迟,cpu使用率很低。
在快速运行中,所有包都包含push和ack,所有这些包的延迟都不超过1毫秒,cpu使用率很高。
我还发现这个相关的问题没有帮助。
为什么这一行简单的代码会有如此大的不同?
为什么java中的简单解决方案这么慢?

bpzcxfmw

bpzcxfmw1#

在历史上,套接字是使用nagle算法打开的,它会延迟小数据包以优化网络通信。
处理小包时,应设置 TCP_NODELAY 插座选项。在java中,您可以通过调用 socket.setTcpNoDelay(true); 调整后我得到:
12000包/秒,无缓冲区
26000包/秒,带缓冲区
我的调整代码:

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);
    }
}

相关问题