Buffered I/O (Buffered I/O)
InputStream.read()
and OutputStream.write()
the object to manipulate is a single byte. Depending on the resources that they access, using these methods can be quite slow.
For example FileInputStream.read()
, when used, the speed will be very slow and heinous. Because each call accesses the operating system's kernel to get 1 bytes of data. In modern operating systems, the kernel tends to use buffered I/O implementations, so this operation does not trigger a disk read operation each time it is invoked. But the buffer is in the kernel after all, so each time the method is called it means that an expensive system call is taken to get to 1 bytes in the kernel I/O buffer.
The same is true for writing data. Each invocation FileOutputStream.write()
method stores one of its own data in the kernel's buffer. Eventually, the kernel writes the contents of the buffer to disk when the file is closed or when the flush method is called.
For file-based binary data I/O (file-based binaries), be sure to encapsulate the underlying file byte stream using Bufferedinputstream or Bufferedoutputstream.
For file-based character data I/O (file-based Character data I/O), be sure to use BufferedReader or bufferedwriter to encapsulate the underlying file character stream one at a time.
In fact, the above best practices are not limited to file I/O, but are applicable to almost all other types of I/O. For example, the byte stream obtained through the socket (through getinputstream ()
and getoutputstream ()
), before using them, be sure to encapsulate them with a buffered filter stream (buffering filter stream).
However, there are exceptions. When using Bytearrayinputstream and Bytearrayoutputstream types, do not use buffered filter streams on them. These two types set an area in memory as a buffer, so when you set a buffer filter stream for them, it is equivalent to having the data copied two times, taking Bytearrayinputstream as an example:
- Buffers from the kernel buffer to the buffered filter stream
- Buffer filter stream from buffer to Bytearrayinputstream
When there are other filter streams (Filtering stream) involved, the use of buffer filter flow requires specific analysis of the problem. For example, in a serialized example:
Private void writeobject(ObjectOutputStream out) throws IOException { if (Prices == NULL) { makeprices(); } out.Defaultwriteobject();}protected void makeprices() throws IOException { Bytearrayoutputstream BAOs = New Bytearrayoutputstream(); ObjectOutputStream Oos = New ObjectOutputStream(BAOs); Oos.writeobject(Prices); Oos.Close();}
Although ObjectOutputStream sends only one byte to the next stream at a time, using bufferedoutputstream is meaningless when the next stream is the final bytearrayoutputstream. This only increases the number of copies of the data, resulting in a decrease in performance.
But when there are other filtering flows between Bytearrayoutputstream and ObjectOutputStream, it might be useful to filter the buffer stream. For example, when you need to compress a byte array using a compressed filter stream:
Private void writeobject(ObjectOutputStream out) throws IOException { if (Prices == NULL) { makezippedprices(); } out.Defaultwriteobject();}protected void makezippedprices() throws IOException { Bytearrayoutputstream BAOs = New Bytearrayoutputstream(); Gzipoutputstream Zip = New Gzipoutputstream(BAOs); Bufferedoutputstream Bos = New Bufferedoutputstream(Zip); ObjectOutputStream Oos = New ObjectOutputStream(Bos); Oos.writeobject(Prices); Oos.Close(); Zip.Close();}
The above adds a bufferedoutputstream between Gzipoutputstream and ObjectOutputStream, The reason for this performance increase is that when the Gzipoutputstream object is a piece of data, the performance is higher than when the operand is a byte.
When you use the Encoder/decoder stream to convert byte data and character data, they are encapsulated with buffered filter streams, and better performance can be achieved.
The following table is a set of the effects of using a buffered filter stream on the final time when serializing/deserializing with compression:
operation |
serialization time |
|
unbuffered compression/decompression |
60.3s |
79.3s |
buffered compression/decompression |
26.8s |
12.7s |
As you can see, the performance boost is so obvious when you add a bufferedoutputstream to Gzipoutputstream and ObjectOutputStream.
Summarize
InputStream.read()
And OutputStream.write()
the performance is relatively low because they just manipulate one byte.
- When working with file streams, socket streams, compressed streams, and character-encoded streams, ensure that buffered filter streams are used to encapsulate them.
[Java Performance] buffered I/O (Buffered I/O)