2

I'm currently using Java sockets in a client-server application with OutputStream and not BufferedOutputStream (and the same for input streams).

The client and server exchanges serialized objects (writeObject() method).

Does it make sense (more speed) to use BufferedOutputStream and BufferedInputStream in this case?

And when I have to flush or should I not write a flush() statement?

jww
  • 97,681
  • 90
  • 411
  • 885
machinery
  • 5,972
  • 12
  • 67
  • 118

2 Answers2

7

Does it make sense (more speed) to use BufferedOutputStream and BufferedInputStream in this case?

Actually, it probably doesn't make sense1.

The object stream implementation internally wraps the stream it has been given with a private class called BlockDataOutputStream that does buffering. If you wrap the stream yourself, you will have two levels of buffering ... which is likely to make performance worse2.

And when I have to flush or should I not write a flush() statement?

Yes, flushing is probably necessary. But there is no universal answer as to when to do it.

  • On the one hand, if you flush too often, you generate extra network traffic.

  • On the other hand, if you don't flush when it is needed, the server can stall waiting for an object that the client has written but not flushed.

You need to find the compromise between these two syndromes ... and that depends on your application's client/server interaction patterns; e.g. whether the message patterns are synchronous (e.g. message/response) or asynchronous (e.g. message streaming).


1 - To be certain on this, you would need to do some forensic testing to 1) measure the system performance, and 2) determine what syscalls are made and when network packets are sent. For a general answer, you would need to repeat this for a number of use-cases. I'd also recommend looking at the Java library code yourself to confirm my (brief) reading.

2 - Probably only a little bit worse, but a well designed benchmark would pick up a small performance difference.


UPDATE

After writing the above, I found this Q&A - Performance issue using Javas Object streams with Sockets - which seems to suggest that using BufferedInputStream / BufferedOutputStream helps. However, I'm not certain whether the performance improvement that was reported is 1) real (i.e. not a warmup artefact) and 2) due to the buffering. It could be just due to adding the flush() call. (Why: because the flush could cause the network stack to push the data sooner.)

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thank you. I'm using synchronouse message patterns. Which flushing principle is good in this case? – machinery Oct 12 '14 at 08:46
  • And if I would use ObjectOutputStream objectOutputStream = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream())); and the same for the input stream, will I have to close also the BufferedOutputStream at the end or is this automatically done by closing the ObjectOutputStream and the socket? – machinery Oct 12 '14 at 08:53
  • Last but not least, do I have to call the flush() on the objectOutputStream or on the BufferedOutputStream? – machinery Oct 12 '14 at 08:56
  • 1) I can't tell you. You (i.e. YOU) need to understand your application to figure out when to flush. 2) If you close a wrapper stream, the wrapped stream is closed. 3) You call `flush()` on the wrapper and it propagates to the wrapped stream. – Stephen C Oct 12 '14 at 12:40
  • Note: all three of those questions you could have answered yourself by reading the javadocs and the source code. You need to learn to do that. You can't always rely on other people being willing to spoon-feed you information. – Stephen C Oct 12 '14 at 12:41
0

I think these links might help you:

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

The flush method flushes the output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination.

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

Internally a buffer array is used and instead of reading bytes individually from the underlying input stream enough bytes are read to fill the buffer. This generally results in faster performance as less reads are required on the underlying input stream.

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

As a means of starting the discussion, here are some basic rules on how to speed up I/O: 1.Avoid accessing the disk. 2.Avoid accessing the underlying operating system. 3.Avoid method calls. 4.Avoid processing bytes and characters individually.

So using Buffered-Streams usually speeds speeds up the IO-processe, as less read() are done in the background.

Community
  • 1
  • 1
Tammo
  • 1
  • 1