El tamaño óptimo del búfer está relacionado con varias cosas: tamaño del bloque del sistema de archivos, tamaño del caché de la CPU y latencia del caché.
La mayoría de los sistemas de archivos están configurados para usar tamaños de bloque de 4096 u 8192. En teoría, si configura el tamaño de su búfer para leer algunos bytes más que el bloque de disco, las operaciones con el sistema de archivos pueden ser extremadamente ineficientes (es decir, si usted configuró su búfer para leer 4100 bytes a la vez, cada lectura requeriría 2 lecturas de bloque por el sistema de archivos). Si los bloques ya están en caché, entonces terminas pagando el precio de RAM -> Latencia de caché L3 / L2. Si no tiene suerte y los bloques aún no están en caché, también paga el precio del disco-> latencia RAM.
Esta es la razón por la que ve que la mayoría de los búferes tienen un tamaño de potencia de 2 y, en general, son más grandes (o iguales) que el tamaño del bloque de disco. Esto significa que una de las lecturas de su flujo podría dar como resultado múltiples lecturas de bloque de disco, pero esas lecturas siempre usarán un bloque completo, sin lecturas desperdiciadas.
Ahora, esto se compensa bastante en un escenario típico de transmisión porque el bloque que se lee del disco todavía estará en la memoria cuando llegue a la siguiente lectura (después de todo, estamos haciendo lecturas secuenciales), así que terminará pagar el precio de latencia de caché RAM -> L3 / L2 en la siguiente lectura, pero no el disco-> latencia RAM. En términos de orden de magnitud, la latencia de disco-> RAM es tan lenta que prácticamente inunda cualquier otra latencia con la que pueda estar lidiando.
Entonces, sospecho que si realizó una prueba con diferentes tamaños de caché (no lo he hecho yo mismo), probablemente encontrará un gran impacto del tamaño de la caché hasta el tamaño del bloque del sistema de archivos. Por encima de eso, sospecho que las cosas se nivelarían bastante rápido.
Aquí hay un montón de condiciones y excepciones: las complejidades del sistema son realmente asombrosas (solo manejar las transferencias de caché L3 -> L2 es increíblemente complejo y cambia con cada tipo de CPU).
Esto lleva a la respuesta del "mundo real": si su aplicación es como el 99%, establezca el tamaño de caché en 8192 y continúe (aún mejor, elija la encapsulación sobre el rendimiento y use BufferedInputStream para ocultar los detalles). Si se encuentra en el 1% de las aplicaciones que dependen en gran medida del rendimiento del disco, cree su implementación para que pueda intercambiar diferentes estrategias de interacción de disco y proporcione los mandos y diales para permitir a sus usuarios probar y optimizar (o inventar algunos sistema de auto optimización).