Tôi đã gần đây đã cố gắng để khám phá hiệu suất IO. Từ những gì tôi đã quan sát, trực tiếp viết thư cho một số FileOutputStream
đã dẫn đến kết quả tốt hơn; mà tôi đã gán cho cuộc gọi bản địa của FileOutputStream
cho write(byte[], int, int)
. Hơn nữa, tôi cũng đã quan sát thấy rằng khi độ trễ của BufferedOutputStream
bắt đầu hội tụ theo hướng trực tiếp FileOutputStream
, nó dao động nhiều hơn tức là nó đột ngột có thể tăng gấp đôi (tôi chưa thể tìm ra lý do).
P.S. Tôi đang sử dụng Java 8 và sẽ không thể nhận xét ngay bây giờ về việc liệu các quan sát của tôi có giữ các phiên bản java trước đó hay không.
Dưới đây là đoạn code tôi thử nghiệm, nơi đầu vào của tôi là một tập tin ~ 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")));
}
}
}
}
OUTPUT:
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]
Nguồn
2017-01-30 15:53:29
Cái gì tôi đã không tìm thấy được nêu ra - các kích thước bộ đệm mặc định của BufferedOutputStream là gì trong Java 6? Bạn đề cập đến 8KB - là mặc định trong Java? Các Javadocs cho 1.4.2 nói rằng bộ đệm là 512 byte, có nghĩa là hầu hết những gì tôi viết có xu hướng giảm từ 200 đến 400 byte cho mỗi mảng. Tuy nhiên, thông tin này được loại bỏ khỏi tài liệu Java 6. –
@Thomas - [xem mã nguồn] (http://www.docjar.com/html/api/java/io/BufferedOutputStream.java.html#51), kích thước mặc định là 8192. Tôi cho rằng chúng loại bỏ các đặc điểm kỹ thuật kích thước mặc định để có thể thay đổi nó khi một "mặc định hợp lý nhất" mới xuất hiện. Nếu có một kích thước bộ đệm cụ thể là quan trọng, có thể bạn sẽ muốn xác định nó một cách rõ ràng. – gustafc
@gustafc Cảm ơn. Tôi luôn quên rằng tôi có thể xem mã nguồn Java. –