使用带套接字的Javas对象流的性能问题

使用带套接字的Javas对象流的性能问题,java,performance,sockets,objectoutputstream,objectinputstream,Java,Performance,Sockets,Objectoutputstream,Objectinputstream,我试图在Java中使用套接字和对象流来实现本地IPC,但是我发现性能很差 我正在测试通过套接字通过ObjectOutputStream发送对象到通过ObjectInputStream接收回复的ping时间 以下是请求者: public SocketTest(){ int iterations = 100; try { Socket socket = new Socket("localhost", 1212); ObjectInputStream

我试图在Java中使用套接字和对象流来实现本地IPC,但是我发现性能很差

我正在测试通过套接字通过ObjectOutputStream发送对象到通过ObjectInputStream接收回复的ping时间

以下是请求者:

public SocketTest(){

    int iterations = 100;
    try {
        Socket socket = new Socket("localhost", 1212);

        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream()); 
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); 

        double start = System.currentTimeMillis();
        for (int i = 0; i < iterations; ++i) {

            Request request = new Request();
            objectOutputStream.writeObject(request);

            Response response = (Response)objectInputStream.readObject();
        }
        double finish = System.currentTimeMillis();
        System.out.println("Per ping: " + (finish - start) / iterations );

    } catch (Exception e) {
        e.printStackTrace();
    }
}
我得到的结果是:

每ping:80.35

对于本地交通来说,80毫秒的速度远远不够慢

请求和响应类非常小,序列化速度很快

我曾天真地尝试添加:

socket.setKeepAlive(true);  
socket.setTcpNoDelay(true);
收效甚微

执行ping本地主机:

64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=64 time=0.035 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.037 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.049 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=64 time=0.039 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=4 ttl=64 time=0.056 ms  
它也很快

Java版本1.6.0_05l
在RedHat 2.4上运行时,您是否尝试将请求和响应嵌入到/?它应该可以大大提高性能。

我希望您必须在两侧调用
objectOutputStream.flush()
,以确保数据立即发送到网络。否则,TCP堆栈可能会等待一段时间,等待更多数据填充部分IP数据包。

除了在每次读取之前使用缓冲流并调用flush(),还应该首先在两端创建ObjectOutputStream。此外,除非您计划调用writeObject(null),否则测试返回null的readObject()是毫无意义的。使用readObject()对EOS的测试是catch(EOFEException exc)。

因此,在构造BufferedInputStream之前,先构造BufferedOutputStream并刷新它。避免上吊

它说根据文件

如果您修改测试用例,使 AServer和AClient构造 对象之前的ObjectOutputStream ObjectInputStream,则测试不会 块这是预期的结果 鉴于以下情况的行为 文件:

ObjectOutputStream构造函数:
创建一个ObjectOutputStream,用于写入指定的
输出流。此构造函数编写 要删除的序列化流标头 下伏河流;来电者可 我想冲洗一下小溪 立即确保 用于接收的构造函数
ObjectInputStreams在 阅读标题

ObjectInputStream构造函数:
创建一个ObjectInputStream,从指定的 输入流。序列化流 从流中读取标头,然后 已证实的此构造函数将阻止 直到相应的
ObjectOutputStream已写入和 冲洗了收割台

我仍然认为它会比那更快。我还能做些什么来改进这一点吗

这似乎是一个微观基准。他们总是很难做到正确,但我认为如果你在开始测量延迟之前先发送2000条消息


另外,请参阅关于如何正确执行微基准测试的详细答案。

我已将两端的内容更改为:ObjectOutputStream ObjectOutputStream=new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream());ObjectInputStream ObjectInputStream=new ObjectInputStream(new BufferedInputStream(socket.getInputStream());而且它有了很大的改进!每平:0.1354我仍然认为它会比这更快。我还可以做些什么来改进这一点吗?是的,我已经添加了这一点,但没有做记录。如果没有刷新,它就无法工作。你的意思是“所以构造ObjectOutputStream并刷新它”。我在研究另一个问题()的答案时遇到了这个问题。令人费解的是ObjectOutputStream本身做了一些缓冲。所以也许是潮水(独自一人)在帮助。。。通过触发网络堆栈立即推送数据。@StephenC否,是按正确顺序创建的,才有帮助。在头创建过程中没有缓冲,除非堆栈中的下层有缓冲输出流。
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=64 time=0.035 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.037 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.049 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=64 time=0.039 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=4 ttl=64 time=0.056 ms