首先给出一个可用的结果,java中ObjectInputStream和ObjectOutputStream网络读写对象速度比较慢。以下给出过程。
今天专门测试了一下java中ObjectInputStream和ObjectOutputStream的网络读写对象的性能。因为某些原因,使用的是Nexus5和PC之间通过USB来调用adb转发功能,从而实现安卓设备和PC之间能够通过socket通信。之所以这样做事因为我们需要使用PC的时间来作为我们多台设备log的时间,每当需要时间的时候,就向PC发起一个请求,PC把自己的时间通过socket来发送给安卓设备。这之间的技术不详细展开。
一开始请求响应逻辑是这样的,首先建立好socket连接,然后在每次需要时间的时候,就发起一个请求,然后就等待PC端给出响应。发出请求的代码如下:
public void sendMsg(final Message msg, final Socket host_socket)
{
ObjectOutputStream oos;
try
{
oos = new ObjectOutputStream(host_socket.getOutputStream());
oos.writeObject(msg);
oos.flush();
} catch (SocketTimeoutException stoe)
{
stoe.printStackTrace();
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
这里逻辑就是,当需要发送的时候,就创建ObjectOutputStream 新对象,调用getOutputStream()得到网络流,然后就开始发送对象。接收过程如下:
public Message receiveMsg(final Socket host_socket)
{
Message msg = null;
try
{
final ObjectInputStream ois = new ObjectInputStream(host_socket.getInputStream());
msg = (Message) ois.readObject();
} catch (StreamCorruptedException sce)
{
sce.printStackTrace();
} catch (IOException ioe)
{
ioe.printStackTrace();
} catch (ClassNotFoundException cnfe)
{
cnfe.printStackTrace();
}
return msg;
}
接收过程也是先创建ObjectInputStream 对象,得到网络流,然后阻塞读流数据。发送和接收方式都是调用这两个接口,然后测试了1000次的发送接收过程,即手机端向PC端发起1000次的时间请求。最后得到平均延迟大约为50ms左右。这里的延迟为从开始发送请求开始,到收到响应时候的时间。这个延迟很大了。
然后接着,我们稍微做了一些优化,我们认为每次得到网络流是需要开销的,这个开销会对延迟影响很大。所以我们在建立完socket连接的时候,就创建ObjectInputStream 和ObjectOutputStream 对象,得到网络流,每次需要发送和接收数据,就调用这两个现成的对象,而不需要重新得到网络流。同样我们测试1000次,手机向PC请求时间并等待PC的响应,最后得到的平均延迟为40ms左右。
然后又做了接下来的一个测试,直接秒杀前面的两个延迟。我们依然使用固定的网络流对象,不是每次发送或者接收就创建新的流对象,只是我们采用的是DataInputStream 和DataOutputStream 来发送和接收基本数据类型,不再如前面发送对象。1000请求,平均延迟在1-2ms之间,一般不超过1.5ms。也就说速度显著提升。
综上所述,发送对象开销会很大,猜测不是因为网络上的数据变多了,可能是因为对象的编码和解码过程,导致接收和发送对象的延迟会比较大。对象在发送之前,肯定是需要按照某种方式编码的,接收之后还需要解码,这一部分会影响到速度。另一个结论就是发送和接收对象尽量不要去创建新的网络流,虽然socket连接没有断,但是网络流每次重新连接,是需要开销的。
以上的测试都是很粗糙的测试,没有严格的设计实验,在严格的科学意义上不具有仅作参考用。