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).
Sí, probablemente depende de varias cosas, pero dudo que haga mucha diferencia. Tiendo a optar por 16K o 32K como un buen equilibrio entre el uso de memoria y el rendimiento.
Tenga en cuenta que debe tener un bloque try / finally en el código para asegurarse de que la secuencia esté cerrada incluso si se produce una excepción.
fuente
En la mayoría de los casos, realmente no importa tanto. Simplemente elija un buen tamaño, como 4K o 16K, y quédese con él. Si está seguro de que este es el cuello de botella en su aplicación, entonces debe comenzar a crear perfiles para encontrar el tamaño óptimo del búfer. Si elige un tamaño que es demasiado pequeño, perderá tiempo haciendo operaciones de E / S adicionales y llamadas de funciones adicionales. Si elige un tamaño que es demasiado grande, comenzará a ver muchos errores de caché que realmente lo retrasarán. No use un búfer más grande que el tamaño de su caché L2.
fuente
En el caso ideal, deberíamos tener suficiente memoria para leer el archivo en una operación de lectura. Ese sería el mejor desempeño porque dejamos que el sistema administre el Sistema de archivos, las unidades de asignación y el HDD a voluntad. En la práctica, tiene la suerte de conocer los tamaños de archivo de antemano, solo use el tamaño de archivo promedio redondeado a 4K (unidad de asignación predeterminada en NTFS). Y lo mejor de todo: cree un punto de referencia para probar múltiples opciones.
fuente
Puede usar los BufferedStreams / lectores y luego usar sus tamaños de búfer.
Creo que BufferedXStreams está utilizando 8192 como el tamaño del búfer, pero como dijo Ovidiu, probablemente debería ejecutar una prueba en un montón de opciones. Realmente va a depender del sistema de archivos y las configuraciones de disco en cuanto a cuáles son los mejores tamaños.
fuente
La lectura de archivos utilizando FileChannel y MappedByteBuffer de Java NIO probablemente dará como resultado una solución que será mucho más rápida que cualquier solución que involucre FileInputStream. Básicamente, asigne memoria a archivos grandes y use buffers directos para archivos pequeños.
fuente
En la fuente de BufferedInputStream encontrará: private static int DEFAULT_BUFFER_SIZE = 8192;
Por lo tanto, está bien que use ese valor predeterminado.
Pero si puede encontrar más información, obtendrá respuestas más valiosas.
Por ejemplo, su adsl puede preferir un búfer de 1454 bytes, eso es debido a la carga útil de TCP / IP. Para los discos, puede usar un valor que coincida con el tamaño de bloque de su disco.
fuente
Como ya se mencionó en otras respuestas, use BufferedInputStreams.
Después de eso, supongo que el tamaño del buffer realmente no importa. O bien el programa está vinculado a E / S, y el tamaño creciente del búfer sobre el valor predeterminado de BIS no tendrá un gran impacto en el rendimiento.
O el programa está vinculado a la CPU dentro de MessageDigest.update (), y la mayor parte del tiempo no se gasta en el código de la aplicación, por lo que ajustarlo no ayudará.
(Hmm ... con múltiples núcleos, los hilos podrían ayudar).
fuente
1024 es apropiado para una amplia variedad de circunstancias, aunque en la práctica puede ver un mejor rendimiento con un tamaño de búfer mayor o menor.
Esto dependería de varios factores, incluido el tamaño de bloque del sistema de archivos y el hardware de la CPU.
También es común elegir una potencia de 2 para el tamaño del búfer, ya que la mayoría del hardware subyacente está estructurado con bloques de archivos y tamaños de caché que son una potencia de 2. Las clases de búfer le permiten especificar el tamaño del búfer en el constructor. Si no se proporciona ninguno, utilizan un valor predeterminado, que es una potencia de 2 en la mayoría de las JVM.
Independientemente del tamaño de búfer que elija, el mayor aumento de rendimiento que verá es pasar del acceso a archivos sin búfer a búfer. El ajuste del tamaño del búfer puede mejorar ligeramente el rendimiento, pero a menos que esté utilizando un tamaño de búfer extremadamente pequeño o extremadamente grande, es poco probable que tenga un impacto significativo.
fuente