Je dernièrement essayé d'explorer les performances IO. De ce que j'ai observé, l'écriture directe à un FileOutputStream
a conduit à de meilleurs résultats; que j'ai attribué à l'appel natif de FileOutputStream
pour write(byte[], int, int)
. De plus, j'ai également observé que lorsque la latence de BufferedOutputStream
commence à converger vers celle de direct FileOutputStream
, elle fluctue beaucoup plus, c'est-à-dire qu'elle peut même brusquement doubler (je n'ai pas encore réussi à savoir pourquoi).
P.S. J'utilise Java 8 et je ne serai pas en mesure de commenter maintenant si mes observations seront valables pour les versions précédentes de Java.
est ici le code je l'ai testé, où mon entrée était un fichier ~ 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")));
}
}
}
}
SORTIE:
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]
Quelque chose que je ne l'ai pas encore trouvé - quelle est la taille de la mémoire tampon par défaut du BufferedOutputStream en Java 6? Vous parlez 8 Ko - est-ce la valeur par défaut en Java? Les Javadocs pour 1.4.2 disent que le tampon est de 512 octets, ce qui signifie que la plupart de ce que j'écris a tendance à tomber entre 200 et 400 octets par tableau. Toutefois, cette information est supprimée de la documentation Java 6. –
@Thomas - [regardant le code source] (http://www.docjar.com/html/api/java/io/BufferedOutputStream.java.html#51), la taille par défaut est 8192. Je suppose qu'ils supprimé la spécification de taille par défaut pour pouvoir la changer quand un nouveau "défaut le plus sensible" apparaît. Si la taille d'un tampon est importante, vous voudrez probablement le spécifier explicitement. – gustafc
@gustafc Merci. J'oublie toujours que je peux regarder le code source Java. –