【问题标题】:Using buffered streams for sending objects?使用缓冲流发送对象?
【发布时间】:2014-12-06 20:20:03
【问题描述】:

我目前在带有 OutputStream 而不是 BufferedOutputStream(输入流也是如此)的客户端-服务器应用程序中使用 Java 套接字。

客户端和服务器交换序列化对象(writeObject() 方法)。

在这种情况下使用 BufferedOutputStream 和 BufferedInputStream 是否有意义(更快)?

当我必须刷新还是不应该编写flush() 语句时?

【问题讨论】:

    标签: java sockets iostream bufferedreader


    【解决方案1】:

    在这种情况下使用 BufferedOutputStream 和 BufferedInputStream 是否有意义(更快)?

    实际上,它可能没有有意义1

    对象流实现在内部用一个名为BlockDataOutputStream 的私有类封装了它所提供的流,该类进行缓冲。如果您自己包装流,您将有两个级别的缓冲...这可能会使性能变差2

    当我必须刷新还是不应该编写flush() 语句时?

    是的,冲洗可能是必要的。但是对于何时去做这件事并没有统一的答案。

    • 一方面,如果刷新过于频繁,会产生额外的网络流量。

    • 另一方面,如果您在需要时不刷新,服务器可能会停止等待客户端已写入但未刷新的对象。

    您需要找到这两种综合症之间的折衷……这取决于您的应用程序的客户端/服务器交互模式;例如消息模式是同步的(例如消息/响应)还是异步的(例如消息流)。


    1 - 为了确定这一点,您需要进行一些取证测试,以 1) 测量系统性能,以及 2) 确定进行了哪些系统调用以及何时发送网络数据包。对于一般性答案,您需要对许多用例重复此操作。我还建议您自己查看 Java 库代码以确认我的(简要)阅读。

    2 - 可能只有 一点点 更差,但设计良好的基准测试会带来很小的性能差异。


    更新

    写完以上内容后,我发现了这个问答 - Performance issue using Javas Object streams with Sockets - 这似乎表明使用 BufferedInputStream / BufferedOutputStream 会有所帮助。但是,我不确定所报告的性能改进是否是 1)真实的(即不是热身伪影)和 2)由于缓冲。这可能只是由于添加了flush() 调用。 (原因:因为刷新可能会导致网络堆栈更快地推送数据。)

    【讨论】:

    • 谢谢。我正在使用同步消息模式。这种情况下哪种冲洗原理好?
    • 如果我会使用 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));对于输入流也是如此,我是否必须在最后关闭 BufferedOutputStream 还是通过关闭 ObjectOutputStream 和套接字自动完成?
    • 最后但同样重要的是,我是否必须在 objectOutputStream 或 BufferedOutputStream 上调用 flush()?
    • 1) 我不能告诉你。您(即您)需要了解您的应用程序以确定何时刷新。 2)如果关闭包装流,则包装流将关闭。 3)您在包装器上调用flush(),它会传播到包装的流。
    • 注意:所有这三个问题您都可以通过阅读 javadocs 和源代码自行回答。你需要学会这样做。你不能总是依赖其他人愿意用勺子喂你信息。
    【解决方案2】:

    我认为这些链接可能会对您有所帮助:

    What is the purpose of flush() in Java streams?

    flush 方法刷新输出流并强制写出任何缓冲的输出字节。 flush 的一般约定是调用它表示,如果先前写入的任何字节已被输出流的实现缓冲,则应立即将这些字节写入其预期目的地。

    How java.io.Buffer* stream differs from normal streams?

    在内部使用缓冲区数组,而不是从底层输入流中单独读取字节,而是读取足够的字节来填充缓冲区。这通常会带来更快的性能,因为底层输入流需要的读取更少。

    http://www.oracle.com/technetwork/articles/javase/perftuning-137844.html

    作为开始讨论的一种方式,这里有一些关于如何加速 I/O 的基本规则: 1.避免访问磁盘。 2.避免访问底层操作系统。 3.避免方法调用。 4.避免单独处理字节和字符。

    因此,使用 Buffered-Streams 通常会加快 IO 进程,因为后台执行的 read() 较少。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-04
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多