Mam ostatnio próbuje zbadać wydajność IO. Z tego co zauważyłem, bezpośrednie napisanie do FileOutputStream
doprowadziło do lepszych wyników; które przypisałem natywnemu wywołaniu FileOutputStream
dla write(byte[], int, int)
. Co więcej, zauważyłem również, że kiedy opóźnienie BufferedOutputStream
zaczyna się zbiegać w kierunku opóźnienia w kierunku bezpośredniej wartości FileOutputStream
, zmienia się ono o wiele więcej, to znaczy może gwałtownie nawet podwajać się (nie byłem jeszcze w stanie dowiedzieć się dlaczego).
P.S. Używam Java 8 i nie będę mógł teraz komentować, czy moje obserwacje będą się utrzymywać dla poprzednich wersji java.
Oto kod I przetestowane, gdzie mój wkład był plik ~ 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")));
}
}
}
}
WYJŚCIE:
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]
Coś jeszcze nie znaleziono - jaki jest domyślny rozmiar bufora dla BufferedOutputStream w Javie 6? Wspomniałeś 8 KB - czy to jest domyślne w Javie? Javadocs dla wersji 1.4.2 mówią, że bufor ma 512 bajtów, co oznacza, że większość tego, co napiszę, ma zazwyczaj wartość od 200 do 400 bajtów na tablicę. Jednak te informacje są usuwane z dokumentacji Java 6. –
@Thomas - [patrząc na kod źródłowy] (http://www.docjar.com/html/api/java/io/BufferedOutputStream.java.html#51), domyślny rozmiar to 8192. Założę się, że usunięto domyślną specyfikację rozmiaru, aby móc ją zmienić, gdy pojawi się nowe "najbardziej sensowne ustawienie domyślne". Jeśli ważny jest określony rozmiar bufora, prawdopodobnie będziesz chciał go wyraźnie określić. – gustafc
@gustafc Dzięki. Zawsze zapominam, że mogę spojrzeć na kod źródłowy Java. –