【问题标题】:Does it really matter the size of the objects you send through a Socket with object input/output streams?通过带有对象输入/输出流的 Socket 发送的对象的大小真的很重要吗?
【发布时间】:2015-11-26 18:07:48
【问题描述】:

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

ObjectOutputStream 在内部是如何工作的?

【问题讨论】:

    标签: java sockets objectoutputstream objectinputstream


    【解决方案1】:

    例如,发送四个Object[5](每个都刷新)是否比发送Object[20] 更好?

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

    如果您还没有这样做,在Socket OutputStreamObjectOutputStream 之间插入BufferedOutputStream 将对性能产生更大的影响。这允许序列化数据在写入套接字流之前在内存中累积。这可能会节省许多系统调用,并且可以将性能提高 几个数量级 ...取决于发送的实际对象。

    (四个Object[5] 对象的表示大于一个Object[20] 对象,这会导致第一种情况下的性能下降。但是,这最多是微不足道的,与刷新和缓冲问题相比微不足道.)

    这个流在内部是如何工作的?

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

    【讨论】:

      【解决方案2】:

      不,没关系,除非您有理由相信网络链接可能会断开,并且部分数据很有用。否则,这听起来像是无缘无故地让代码变得更复杂的一种方法。

      【讨论】:

        【解决方案3】:

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

        何时以及如何刷新 ObjectStream 完全取决于您使用的流类型。 (考虑到这一切,请记住,并非所有的 OutputStream 扩展都保证尊重您的刷新请求——it is entirely implementation independent,正如 javadocs 的“合同”中所述。)

        但我们当然可以对其进行推理,甚至调出代码,看看实际做了什么。

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

        什么更有效?

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

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

        【讨论】:

          猜你喜欢
          • 2015-03-11
          • 2013-11-14
          • 1970-01-01
          • 1970-01-01
          • 2012-06-19
          • 2012-12-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多