Últimamente he estado tratando de explorar el rendimiento IO. Por lo que he observado, escribir directamente en FileOutputStream
ha conducido a mejores resultados; que he atribuido a la llamada nativa FileOutputStream
para write(byte[], int, int)
. Además, también he observado que cuando la latencia de BufferedOutputStream
comienza a converger hacia la del FileOutputStream
directo, fluctúa mucho más, es decir, puede duplicarse abruptamente (todavía no he podido averiguar por qué).
P.S. Estoy usando Java 8 y no podré comentar en este momento si mis observaciones se mantendrán para las versiones anteriores de Java.
Aquí está el código que probé, donde mi entrada era un archivo ~ 10KB
public class WriteCombinationsOutputStreamComparison {
private static final Logger LOG = LogManager.getLogger(WriteCombinationsOutputStreamComparison.class);
public static void main(String[] args) throws IOException {
final BufferedInputStream input = new BufferedInputStream(new FileInputStream("src/main/resources/inputStream1.txt"), 4*1024);
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int data = input.read();
while (data != -1) {
byteArrayOutputStream.write(data); // everything comes in memory
data = input.read();
}
final byte[] bytesRead = byteArrayOutputStream.toByteArray();
input.close();
/*
* 1. WRITE USING A STREAM DIRECTLY with entire byte array --> FileOutputStream directly uses a native call and writes
*/
try (OutputStream outputStream = new FileOutputStream("src/main/resources/outputStream1.txt")) {
final long begin = System.nanoTime();
outputStream.write(bytesRead);
outputStream.flush();
final long end = System.nanoTime();
LOG.info("Total time taken for file write, writing entire array [nanos=" + (end - begin) + "], [bytesWritten=" + bytesRead.length + "]");
if (LOG.isDebugEnabled()) {
LOG.debug("File reading result was: \n" + new String(bytesRead, Charset.forName("UTF-8")));
}
}
/*
* 2. WRITE USING A BUFFERED STREAM, write entire array
*/
// changed the buffer size to different combinations --> write latency fluctuates a lot for same buffer size over multiple runs
try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream("src/main/resources/outputStream1.txt"), 16*1024)) {
final long begin = System.nanoTime();
outputStream.write(bytesRead);
outputStream.flush();
final long end = System.nanoTime();
LOG.info("Total time taken for buffered file write, writing entire array [nanos=" + (end - begin) + "], [bytesWritten=" + bytesRead.length + "]");
if (LOG.isDebugEnabled()) {
LOG.debug("File reading result was: \n" + new String(bytesRead, Charset.forName("UTF-8")));
}
}
}
}
SALIDA:
2017-01-30 23:38:59.064 [INFO] [main] [WriteCombinationsOutputStream] - Total time taken for file write, writing entire array [nanos=100990], [bytesWritten=11059]
2017-01-30 23:38:59.086 [INFO] [main] [WriteCombinationsOutputStream] - Total time taken for buffered file write, writing entire array [nanos=142454], [bytesWritten=11059]
algo que no he encontrado todavía - ¿cuál es el tamaño de búfer predeterminado de la BufferedOutputStream en Java 6? Mencionas 8 KB: ¿es el valor predeterminado en Java? Los Javadocs para 1.4.2 dicen que el búfer es de 512 bytes, lo que significa que la mayor parte de lo que escribo tiende a estar entre 200 y 400 bytes por matriz. Sin embargo, esta información se elimina de la documentación de Java 6. –
@Thomas - [mirando el código fuente] (http://www.docjar.com/html/api/java/io/BufferedOutputStream.java.html#51), el tamaño predeterminado es 8192. Supongo que eliminó la especificación de tamaño predeterminada para poder cambiarla cuando aparece un nuevo "valor predeterminado más razonable". Si es importante tener un tamaño de búfer específico, es probable que desee especificarlo explícitamente. – gustafc
@gustafc Gracias. Siempre me olvido de que puedo mirar el código fuente de Java. –