java套接字速度异常低
我只是从这个论坛复制了一个数据传输的例子,并在我的程序中使用了它,但我看不出它的速度有什么问题。我测试了主要示例,它在不到30毫秒的时间内传输了大约1MB的数据。读写速度都很好。但当我在我的案例中使用它时,相同数量的数据不会在不到400毫秒的时间内传输!写作仍然有效,但阅读却有问题 在这里,数据被写入。现在,我不想加速第一部分,即对象的序列化。我的问题是关于第二部分java套接字速度异常低,java,Java,我只是从这个论坛复制了一个数据传输的例子,并在我的程序中使用了它,但我看不出它的速度有什么问题。我测试了主要示例,它在不到30毫秒的时间内传输了大约1MB的数据。读写速度都很好。但当我在我的案例中使用它时,相同数量的数据不会在不到400毫秒的时间内传输!写作仍然有效,但阅读却有问题 在这里,数据被写入。现在,我不想加速第一部分,即对象的序列化。我的问题是关于第二部分 private static void writeObject(OutputStream out, Object obj) thr
private static void writeObject(OutputStream out, Object obj) throws IOException {
long t1 = System.currentTimeMillis();
ByteArrayOutputStream bArr = new ByteArrayOutputStream();
ObjectOutputStream ojs = new ObjectOutputStream(bArr);
ojs.writeObject(obj);
ojs.close();
long t2 = System.currentTimeMillis();
byte[] arr = bArr.toByteArray();
int len = arr.length;
for (int i = 0; i < arr.length; i += BUFFER_SIZE)
out.write(arr, i, Math.min(len - i, BUFFER_SIZE));
out.close();
long t3 = System.currentTimeMillis();
System.out.println(t3 - t2);
}
下面是main()
:
我哪里出错了 (关于的强制性评论)
看起来您正在启动两个线程,一个读线程和一个写线程。按照以下顺序进行是完全可行的:
t1
read()
,但由于没有可用数据而被阻止write()
read()
调用返回t2
等,然后退出现在,如果您看到
t2-t1
有大约400ms的时间,这可能不是正在发生的事情:写入线程对sleep()
的调用似乎很可能是在录制t1
之前发生的。但简单的回答是,似乎不清楚t2-t1
在测量什么。特别是,期望它仅测量执行工作所需的时间(而不是等待数据读取)似乎是不正确的。如果您想使用缓冲IO进行读取和写入,可以分别使用和进行读取和写入。而且,你可以使用一个按钮来关闭。写,比如
private static final int BUFFER_SIZE = 32 * 1024;
private static void writeObject(OutputStream out, Object obj) //
throws IOException {
try (ObjectOutputStream ojs = new ObjectOutputStream(//
new BufferedOutputStream(out, BUFFER_SIZE));
ojs.writeObject(obj);
}
}
读起来像
private static Object readObject(InputStream in) throws IOException,//
ClassNotFoundException {
try (ObjectInputStream ois = new ObjectInputStream(//
new BufferedInputStream(in, BUFFER_SIZE))) {
return ois.readObject();
}
}
当您执行微基准测试时,我建议您至少在CPU时间的前2秒忽略所有结果,以便给JVM一个预热的机会 我会写这篇文章而不用睡觉 为了测试的目的,编写对象是不相关的。您只需编写一个
新字节[size]
并查看需要多长时间
为了测试短延迟,我将使用System.nanoTime()
我会先写一条短信,看看往返时间。i、 客户端向服务器发送一个数据包,服务器再次将其发送回来
最后但并非最不重要的一点是,通过使用Java1.4(2004)中添加的NIO,您将获得更好的性能
下面是一些前面编写的代码,它会产生如下结果
On a E5-2650 v2 over loopback
Throughput was 2880.4 MB/s
Loop back echo latency was 5.8/6.2 9.6/19.4 23.2us for 50/90 99/99.9 99.99%tile
注意:这些时间是将数据包发送到服务器并再次发送的完整往返时间。计时单位为微秒
我刚刚复制了一个工作示例
不,你没有。你编了一些完全不同的东西
int len = arr.length;
for (int i = 0; i < arr.length; i += BUFFER_SIZE)
out.write(arr, i, Math.min(len - i, BUFFER_SIZE));
然而,这一切只会增加延迟和浪费空间。私有静态void writeObject(OutputStream out,Object obj)抛出IOException{ long t1=System.currentTimeMillis(); out.writeObject(obj); out.close(); long t2=System.currentTimeMillis()
ByteArrayOutputStream
中没有任何意义,向真实的ObjectOutputStream
中写入的字节数超过其中的字节数是完全无效的。基准测试操作中没有任何意义,永远不应该发生
为什么要关闭
ObjectOutputStream
是另一个谜。可能在接收端也有类似的代码:使用ObjectInputStream.readObject()重新复制所有内容。
为什么要将内容压缩到字节[]
s?@ElliottFrisch我还能怎么做缓冲?你确定数字吗?1GB的30毫秒传输速度为267 Gbit/s(无开销)!哦,对不起,是1MB!我刚刚编辑了我的帖子。但是问题显然没有解决!!你是对的!但问题仍然存在!!正如你在我编写的代码中看到的,由于线程的睡眠()
。我刚刚把它扩展到了2秒,而且它变得更好了。现在它的写入时间不到10毫秒,但读取时间超过100毫秒。正如我所提到的,主要示例在这两方面都用的时间要少得多。此外,我想在服务器/客户端程序中使用该技术,客户端发送一些数据,然后等待回答。如果一秒钟不够,因此,当它等待服务器响应时,问题就更大了。我猜sleep()
将用作临时同步机制,以便在写入线程的Socket()之前调用读取器线程的accept()
。我想知道如果你在读线程调用accept()
和readObject()
之间再加一次睡眠,你会得到什么值,这样写线程(大概)在开始阅读之前就完成了写。是的!这改变了故事!但是当我把sleep()放在
正如您所建议的,读取时间减少到10毫秒以下,但是当我删除sleep()时,写入时间却增加到100毫秒以上
这些数字被交换了!!为什么?!@user1389026我怀疑睡眠并没有真正影响这些方法的性能。除了线程何时被调度这一显而易见的秘密之外,read()
和write()
是从缓冲区获取或写入缓冲区的方法。它们可能需要等待缓冲区准备好进行操作,而不需要进行实际的数据传输工作。Elliott,BufferedXXXXStream
的默认缓冲区大小是多少?。好的,您对测试的看法是正确的。但问题在于实际情况!
On a E5-2650 v2 over loopback
Throughput was 2880.4 MB/s
Loop back echo latency was 5.8/6.2 9.6/19.4 23.2us for 50/90 99/99.9 99.99%tile
int len = arr.length;
for (int i = 0; i < arr.length; i += BUFFER_SIZE)
out.write(arr, i, Math.min(len - i, BUFFER_SIZE));
out.write(arr, 0, len);
System.out.println(t2-t1);
}