使用带套接字的Javas对象流的性能问题
我试图在Java中使用套接字和对象流来实现本地IPC,但是我发现性能很差 我正在测试通过套接字通过ObjectOutputStream发送对象到通过ObjectInputStream接收回复的ping时间 以下是请求者:使用带套接字的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
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