When I construct a new BufferedReader it is providing me a buffer of 8192 characters. What is the logic/reason behind this?
8192 = 2 to the power of 13
Traditionally, memory managers and paging files in the operating system work on pages that are sized in powers of 2. This allows very efficient multiply/divide operations to be performed with left/right shift operations. When working with a buffer, the worst case scenario is to have a buffer with size 1 byte longer than the page size (that would result in an extra page swap with very low benefit). So the default buffer sizes will also tend to be implemented in factors of two.
I'd assume (but have not checked) that the JVM looks for buffers like this and attempts to align them on page boundaries.
Why does this matter? Page misses are quite expensive. If you are doing a ton of IO, it's better to avoid the case where the page backing the buffer gets swapped out to disk (kind of defeats the purpose of the buffer). That said, for most applications, this is a micro-optimization, and for the vast majority of cases, the default is fine.
For reference, Windows and Linux both currently use a 4KB memory page size. So the default buffer on BufferedReader will consume exactly 2 pages.
As the BufferedReader Javadoc says
The buffer size may be specified, or the default size may be used. The default is large enough for most purposes.
The default was chosen as being "large enough" (which I would interpret as "good enough").
8192, as you said, is 2^13. The exact reason for this number being the default is hard to come by, but I'd venture to say it's based on the combination of normal use scenarios and data efficiency. You can specify a buffer size of whatever you want, though, using a different object constructor.
BufferedReader(Reader in, int sz)
Creates a buffering character-input stream that uses an input buffer of the specified size.
https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html
and BufferedReader default buffer size? will provide further insight.
There is a JDK ticket https://bugs.openjdk.org/browse/JDK-4953311 that states
Most OSes that we support uses a buffer size of 8192 (8K) bytes for their IO buffering, and this is also the buffer size used by Microsoft VM on Win32. We should change the default buffer size in these two classes to 8K.
8192 is 2^13 and also reveals much information regarding the RIGHT v WRONG encoded in all we do. If one takes away or adds to the author intent, he modifies and therefore corrupts the entire thing. Try to add or take away from something perfect... good luck!
Related
What are intended use cases for the BitmapFactory.Options.inTempStorage option?
Documentation is pretty terse on this:
Temp storage to use for decoding. Suggest 16K or so.
If I'm not mistaken it means that if you don't provide the buffer explicitly, it would create and use one by itself.
So the only benefit I see is reusing the same 16K buffer for multiple decodings which seems to have quite questionable impact on performance/memory usage optimization.
So why SDK authors give us control over the temp storage for decoding? Should providing much greater buffer improve decoding performance?
Can someone expand on this?
It seems that your assumption is the correct one - this option is mainly for recycling the buffer itself.
From the Android Source Code:
// pass some temp storage down to the native code. 1024 is made up,
// but should be large enough to avoid too many small calls back
// into is.read(...) This number is not related to the value passed
// to mark(...) above.
byte [] tempStorage = null;
if (opts != null) tempStorage = opts.inTempStorage;
if (tempStorage == null) tempStorage = new byte[16 * 1024];
This means that if you do not send this buffer, it will be allocated. Though does not look like an optimization for most cases, if you load many small images - the allocation of a 16K buffer per image might be pricy.
Regarding the buffer size, as you can see from the comments in the code - there is no magic number. What happens is that the Native code that decodes the image, uses the InputStream managed code to fetch the actual raw bytes (from disk/network etc). It uses the allocated buffer to communicate the bytes for each READ call. So, it is really depends on the InputStream. For example, disk IS might read from the disk in a bulk of 4k and then 16k is more than enough - passing in a buffer bigger than that will not improve the performance since the buffer will not fill up more than 4k at each READ call.
In any case, considering this kind of optimization should be for a really specific cases - if you have such a case, you can provide a bigger buffer and see if it has any affect on the performance.
I was first curious about how the buffer size of 'BufferedInputStream' class is decided for each program. I found out in STACKOVERFLOW that the default buffer size is 8KB.
I wonder if there is profound meaning in the default buffer size of
'BufferInputStream' class, which is 8KB in size.
When I searched java docs for information about the 'BufferedInputStream' class,
I found out there are two forms of constructors for the class.
One constructor form offers users the ability to change the buffer size.
BufferedInputStream(InputStream in, int size)
Could the buffer size of this class be critical in deciding performance of some programs? I'm curious if anyone uses the above form of the constructor to change the buffer size to fit/optimize his/her program.
Is there any profound meaning to the default buffer size of 8KB?
Thank you for reading.
Could the buffer size of this class be critical in deciding performance of some programs? I'm curious if anyone uses the above form of the constructor to change the buffer size to fit/optimize his/her program.
Probably not. Changing from a buffer size of 1 to 2 will about double your performance (by reducing system calls). Changing from 2 to 4 will double it again. Changing from 4 to 8, again. You get the idea. At some point this ceases being true, as the performance ceases being dominated by system calls and starts being dominated by transfer sizes. 8k is a good place to stop. Use more if you like but you won't notice much difference.
Is there any profound meaning to the default buffer size of 8KB?
There isn't. It is 8k in size. By default. That's the meaning. You can change it via a constructor. Nothing more to it.
I have made an application in android that lets the user compress and decompress files and I used the package java.util.zip. Everything is okay. the speed, files are totally compressed and decompressed together with the directories. The only problem is that the application is not able to compress/decompress large files (greater than 1gb).
I believe the problem is the size of my buffer. Other codes that I've seen, the value of their buffer is 1024 or 2048 or 8192 but my value of my buffer is base on the size of the chosen file (just to make it flexible). But once the user chose a large file (with a size of >8 digits), that's were the error comes out. I searched over the net and also here in this site but I can't find an answer. my problem is similar to this:
To Compress a big file in a ZIP with Java
Thanks for the future help! :)
EDIT:
Thanks for the comments and answers. It really helped a lot. I thought BUFFER in compressing/decompressing in java means the size of file so in my program, I made the buffer size flexible (buffer size = file size). Will someone please explain how buffer works so I can understand why is it okay that BUFFER has a fixed value. Also for me to figure it out why others people is telling that it is much better if the buffer size is 8k or else. Thanks a lot! :)
If you size the buffer to the size of the file, then it means that you will have OutOfMemoryError whenever the file size is too big for memory available.
Use a normal buffer size and let it do it's work - buffering the data in a streaming fashion, one chunk at a time, rather than all in one go.
For explanation, see for example the documentation of BufferedOutputStream:
The class implements a buffered output stream. By setting up such an
output stream, an application can write bytes to the underlying output
stream without necessarily causing a call to the underlying system for
each byte written.
So using a buffer is more efficient than non-buffered writing.
And from the write method:
Ordinarily this method stores bytes from the given array into this
stream's buffer, flushing the buffer to the underlying output stream
as needed. If the requested length is at least as large as this
stream's buffer, however, then this method will flush the buffer and
write the bytes directly to the underlying output stream.
Each write causes the in-memory buffer to fill up, until the buffer is full. When the buffer is full, it is flushed and cleared. If you use a very large buffer, you will cause a large amount of data to be stored in memory before flushing. If your buffer is the same size as the input file, then you are saying you need to read the whole content into memory before flushing it. Using the default buffer size is usually just fine. There will be more physical writes (flushes); you avoid exploding memory.
By allowing you to specify a specific buffer size, the API is letting you choose the right balance between memory consumption and i/o to suit your application. If you tune your application for performance, you might end up tweaking buffer size. But the default size will be reasonable for many situations.
It sounds like it would help to simply set a maximum size for the buffer, something like:
//After calculating the buffer size bufSize:
bufSize = Math.min(bufSize, MAXSIZE);
I need a byte buffer class in Java for single-threaded use. The buffer should resize when it's full, rather than throw an exception or something. Very important issue for me is performance.
What would you recommend?
ADDED:
At the momement I use ByteBuffer but it cannot resize. I need one that can resize.
Any reason not to use the boring normal ByteArrayOutputStream?
As mentioned by miku above, Evan Jones gives a review of different types and shows that it is very application dependent. So without knowing further details it is hard to speculate.
I would start with ByteArrayOutputStream, and only if profiling shows it is your performance bottleneck move to something else. Often when you believe the buffer code is the bottleneck, it will actually be network or other IO - wait until profiling shows you need an optimisation before wasting time finding a replacement.
If you are moving to something else, then other factors you will need to think about:
You have said you are using single threaded use, so BAOS's synchronization is not needed
what is the buffer being filled by and fed into? If either end is already wired to use Java NIO, then using a direct ByteBuffer is very efficient.
Are you using a circular buffer or a plain linear buffer? If you are then the Ostermiller Utils are pretty efficient, and GPL'd
You can use a direct ByteBuffer. Direct memory uses virtual memory to start with is only allocated to the application when it is used. i.e. the amount of main memory it uses re-sizes automagically.
Create a direct ByteBuffer larger than you need and it will only consume what you use.
you can also write manual code for checking the buffer content continously and if its full then make a new buffer of greater size and shift all the data in that new buffer.
I have a theoretical question. Let's imagine you have an InputStream and an OutputStream. You nead to copy content from one to the other and you don't know exactly the size of the content you need to transfer. What is the best choice in general of the block size in the write method?
The answer is: it depends. For a general solution, stop worrying about it and just use a library. Common choices:
Apache Commons IO IOUtils#copy() or copyLarge(), or
Google Guava's ByteStreams#copy()
The default buffer size for BufferedInputStream and BufferedOutputStream is 8 KB and this is typically a good size.
Note: if you are reading a Socket fast enough, you will rarely get more one packet, ~1.5 KB. If you are reading from disk, you typically get whatever size you ask for, however the performance doesn't improve much from 32 KB to 256 KB and is likely to be dependant on the hardware you use.
However I have also found, unless you are benchmarking you rarely see a noticeable difference if you use only 512 bytes as a buffer size (which Inflator/Deflator streams do) i.e. the difference might be 15% or less.
In summary, you are unlikely to notice a difference with buffer sizes between 512 bytes and 32 KB. The latter is likely to be more than enough for most situations. I tend to use 256 KB as I have a lot of memory and few pre-allocated buffers.