Java套接字性能瓶颈:在哪里? [英] Java socket performance bottleneck: where?

查看:50
本文介绍了Java套接字性能瓶颈:在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始开发使用网络的应用程序.第一次尝试使用RMI,由于几个原因,我们切换到纯套接字.但是,在通过网络甚至在本地主机上测试套接字时,我们的速率下降为每秒25个请求.使用RMI时要高两个数量级.

I recently started the development of an application making intensive usage of networking. A first attempt was made using RMI and for a couple of reasons, we switched over to pure sockets. However, when testing sockets over a network, or even on localhost, we dropped to a rate of 25 requests/second. While using RMI it was two orders of magnitude higher.

经过更多测试,我们获得了(对于localhost)以下内容:

With a little more testing, we obtained following (for localhost):

  • 发送始终相同的对象:31628个请求/秒
  • 总是发送一个新对象:每秒25个请求
  • 仅对象创建速度:每秒3-4百万(因此这不是瓶颈)

这是客户端代码:(服务器端只是回复"ACK")

Here is the client code: (the server side just replies an "ACK")

public static void main(String[] args) throws IOException, ClassNotFoundException
{
    Socket kkSocket = null;
    ObjectOutputStream out = null;
    ObjectInputStream in = null;


    kkSocket = new Socket("barium", 4444);
    out = new ObjectOutputStream(kkSocket.getOutputStream());
    in = new ObjectInputStream(kkSocket.getInputStream());


    long throughput;
    long millis;

    TcpRequest hello = null;


    throughput = 0;
    millis = System.currentTimeMillis();
    while (System.currentTimeMillis() < millis + 1000)
    {
        hello = new TcpRequest();
        hello.service = "hello";
        hello.payload = Math.random();
        throughput++;
    }

    System.out.println("-------------------------------------------------------");
    System.out.println("|        Objects created: " + (throughput)  + " requests/sec.");
    System.out.println("-------------------------------------------------------");


    throughput = 0;
    millis = System.currentTimeMillis();
    while (System.currentTimeMillis() < millis + 1000)
    {
        out.writeObject(hello);
        Object res = in.readObject();
        throughput++;
    }
    System.out.println("-------------------------------------------------------");
    System.out.println("|        Same object throughput: " + (throughput)  + " requests/sec.");
    System.out.println("-------------------------------------------------------");


    throughput = 0;
    millis = System.currentTimeMillis();
    while (System.currentTimeMillis() < millis + 1000)
    {
        hello = new TcpRequest();
        out.writeObject(hello);
        Object res = in.readObject();
        throughput++;
    }
    System.out.println("-------------------------------------------------------");
    System.out.println("|        New objetcs throughput: " + (throughput)  + " requests/sec.");
    System.out.println("-------------------------------------------------------");


    out.close();
    in.close();

    kkSocket.close();
}

TcpRequest类只是一个没有任何特殊要求的伪类.

The TcpRequest class is just a dummy class without anything special.

所以,如果创建对象的速度很快,如果通过网络发送它的速度很快...为什么地球上的通过网络发送新对象的速度如此之慢?!?!

So, if creating object is fast, if sending it over the network is fast ...why on earth is sending a new object over the network so slow?!?!

如果您保留相同的对象并在发送之前修改其内容,则传输速率也将很高...但是会陷入令人讨厌的陷阱:

And if you keep a same object and modify its content before sending it, you will also have high transfer rate ...but fall in the nasty pitfall:

使用对象序列化时重要的是要记住ObjectOutputStream维护一个哈希表映射写入的对象放入流中进行处理.当一个对象被写入流第一次,其内容将是复制到流中.随后的写,但是,导致被写入对象流.

When working with object serialization it is important to keep in mind that the ObjectOutputStream maintains a hashtable mapping the objects written into the stream to a handle. When an object is written to the stream for the first time, its contents will be copied to the stream. Subsequent writes, however, result in a handle to the object being written to the stream.

...这发生在我们身上,并导致了数小时的调试,然后才弄清楚.

...which happened to us and caused some hours of debugging before figuring it out.

所以基本上...如何通过套接字实现高吞吐量?(...我的意思是,由于RMI是它的包装,我们已经高了两个数量级!)

So basically ...how do you achieve high throughput with sockets? (...I mean, with RMI being a wrapper around it we were already two orders of magnitude higher!)

已解决:

通过替换:

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

使用:

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

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

The performances are normal again (nearly the same high throughput as with the same object case)

推荐答案

找到了它:

代替:

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

您应该使用:

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

还有

out.flush();

发送消息时

...有很大的不同...虽然我不知道为什么.

...makes a huge difference ...though I don't know exactly why.

这篇关于Java套接字性能瓶颈:在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆