How big should my input stream buffer be?
In Sun's current implementation, the default buffer size for a
BufferedInputStream is 8K. On certain systems at least, this appears to
be about the "point of diminishing return" at which increasing the buffer size
does not improve either overall read time or CPU usage.
(And after all, Sun probably chose this size for a reason!)
In other words, unless you've some reason not to, you may as well
stick to the default.
The size of the read buffer affects both overall time taken to read the data
plus the CPU time used. As a rule, both diminish as buffer size
is increased, but overall time tends to plateau quickly as buffer
size is increased. Even at the point where increasing the buffer size gives no
gain in overall time to read the data, CPU time can continue to diminish. In other
words, a large buffer size will probably benefit applications that are performing
simultaneous reading and processing of data, but won't bring
much benefit to single-threaded applications that must wait for the data before
proceeding.
The graph below shows some example measurements of elapsed and CPU time
as buffer size is increased. In each run of this test, the contents of 10 files each of
50MB in size were read in via a BufferedInputStream of the given size1.
(In this case, the test system was a 2GHz uniprocessor Windows system with a
standard 7,200 RPM hard drive.)
In this test case, overall read time plateaus at a buffer size of around
192 bytes. However, at this buffer size, we burn aroun 25% of the CPU.
Beyond this buffer size, CPU usage continues to decrease even though overall
read time remains more or less constant. At a buffer size of around 1K,
we use in the order of 10% of the CPU while reading through the file.
Effect of larger buffer sizes on CPU usage
In our test case here, there appears to be a slight benefit in terms of
CPU usage when the buffer size is made a little larger than 1K. However, beyond
around 8-10K, CPU usage settles to around 4.5-5% (although the measured
CPU usage fluctuates a little from run to run).
1. This size was chosen to try and minimise the effect of OS buffering on
read performance. In the test configuration, the OS appeared to buffer up to
around 100MB of data. So the overall 500MB of data meant that at the start
of a run, there was probably little or no useful data in the file system caches
left behind by the previous run.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.