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

时间:2010-02-12 10:21:29

标签: java performance sockets objectoutputstream objectinputstream

我正在尝试使用Java中的套接字和对象流来进行本地IPC,但是我看到性能很差。

我正在测试通过ObjectOutputStream发送对象的ping时间,以通过Socket上的ObjectInputStream接收回复。

这是请求者:

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

这是响应者:

public ServerSocketTest(){

    try {

        ServerSocket serverSocket = new ServerSocket(1212);
        Socket socket = serverSocket.accept();

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

        Request request = (Request)objectInputStream.readObject();
        while (request != null) {

            Response response = new Response();
            objectOutputStream.writeObject(response);
            request = (Request)objectInputStream.readObject();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我得到的结果是:

Per ping:80.35

对于当地交通而言,80毫秒的速度非常慢。

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

我试过天真添加:

socket.setKeepAlive(true);  
socket.setTcpNoDelay(true);

影响不大。

执行ping localhost:

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上运行

5 个答案:

答案 0 :(得分:5)

您是否尝试在BufferedInputStream / BufferedOutputStream中嵌入请求ts和响应?它应该广泛地改善表现。

答案 1 :(得分:1)

因此构建BufferedOutputStream&amp;在构造BufferedInputStream之前刷新它。为了避免挂起。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4788782

根据文件说明

  

如果您修改测试用例   AServer和AClient构造   之前的ObjectOutputStream   ObjectInputStream,测试没有   块。这是预期的   给出以下行为   文件:

     

ObjectOutputStream构造函数:
      创建一个写入指定
的ObjectOutputStream   的OutputStream。这个构造函数写道   序列化流标头到   底层流;来电者可以   希望冲洗流   立即确保   接收的施工人员   ObjectInputStreams不会阻塞   读标题。

     

ObjectInputStream构造函数:
      创建一个从指定的
中读取的ObjectInputStream   的InputStream。序列化流   标头是从流中读取的   验证。这个构造函数会阻塞   直到相应的   ObjectOutputStream已编写和   刷了头。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

  

我仍然认为它会比那更快。我还能做些什么来改善这个吗?

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

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

答案 4 :(得分:-1)

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