通过具有对象输入/输出流的Socket发送的对象的大小是否真的重要?

时间:2011-04-28 01:22:01

标签: java sockets objectoutputstream objectinputstream

在每次单独调用flush the OutputStream之后ObjectOutputStream#writeObject更有效率,而不是在一系列对象写入后刷新流? (例如:写对象并刷新4次,或写4次然后只刷一次?)

ObjectOutputStream如何在内部运作?

3 个答案:

答案 0 :(得分:2)

  

例如,以某种方式更好地发送四个Object[5](每个都刷新)而不是Object[20]吗?

不是更好。事实上,从性能的角度来看,它可能更糟糕。每次刷新都会强制操作系统级TCP / IP堆栈“立即”发送数据。如果您最后只进行一次刷新,则应节省系统调用和网络流量。

如果您尚未执行此操作,则在BufferedOutputStream SocketOutputStream之间插入ObjectOutputStream会对性能产生更大的影响。这允许序列化数据在写入套接字流之前在内存中累积。这可能会节省许多系统调用,并且可以通过数量级来提高性能......具体取决于发送的实际对象。

(四个Object[5]个对象的表示大于一个Object[20]个对象,在第一个案例中会导致性能下降。但是,这个数据最多是边缘的,与冲洗和缓冲问题。)

  

此流如何在内部工作?

这是一个太明智的问题,无法合理回答。我建议您从this page上的文档开始阅读序列化。

答案 1 :(得分:1)

不,这没关系,除非你有理由相信网络链接可能会下降,部分数据是有用的。否则,它听起来就像是一种让代码变得更加复杂的方法。

答案 2 :(得分:1)

如果查看the one and only public constructor of ObjectOutputStream,您会注意到它需要基础OutputStream进行实例化。

刷新ObjectStream的时间和方式完全取决于您使用的流的类型。 (并且在考虑所有这些时,请记住,并非所有OutputStream扩展都保证尊重您的刷新请求 - it is entirely implementation independent,因为它是在javadocs的'合同'中拼写出来的。)

但当然我们可以推理它,甚至提取代码,看看实际做了什么。

IFF底层OutputStream必须利用设备的OS服务(例如磁盘或the network interface in case of Sockets),然后flush()的行为完全取决于操作系统。例如,您可以获取套接字的输出流,然后实例化ObjectOutputStream以将序列化对象写入网络。主机操作系统的TCP / IP实现负责。

什么更有效?

好吧,如果您的对象流正在包裹ByteArrayOutputStream,那么您可能会查看一系列realloc和System.arrayCopy()调用。我可能会说,因为字节数组的实现使每个(内部)resize()操作的大小加倍,并且每次编写n(小)对象和刷新都不太可能导致n个realloc。 (假设n是一个相当小的数字)。

但是如果要包装网络流,则必须记住网络写入非常昂贵。如果您的协议允许,它会更有意义地将您的写入块(填充发送缓冲区)并刷新一次。