File IO vs NIO 성능 테스트
텍스트 파일 읽기/쓰기 속도는 IO 보다 NIO가 항상 빠르다. NIO는 대용량 트래픽에 더 좋은 성능을 낸다고 하니 다중 사용자를 가정해 여러 쓰레드를 만들어 통신 후 테스트하면 NIO의 성능이 더 극대화 될 것으로 예상된다.
실행 결과
횟수
1차
File NIO가 I/O 보다 29.25% 빠릅니다.
2차
File NIO가 I/O 보다 49.72% 빠릅니다.
3차
File NIO가 I/O 보다 54.59% 빠릅니다.
4차
File NIO가 I/O 보다 40.58% 빠릅니다.
5차
File NIO가 I/O 보다 20.59% 빠릅니다.
6차
File NIO가 I/O 보다 32.32% 빠릅니다.
7차
File NIO가 I/O 보다 16.06% 빠릅니다.
8차
File NIO가 I/O 보다 37.34% 빠릅니다.
코드
/**
* File IO vs NIO 성능 측정
* 둘다 블로킹 모드임
*/
public class IO_vs_NIO {
private static final String FILE_PATH = Paths.get("src", "main", "java", "yoochul", "week04", "sample.txt").toString();
private static final String COPY_PATH = Paths.get("src", "main", "java", "yoochul", "week04", "sample_copy.txt").toString();
private static final int BUFFER_SIZE = 8192;
private static final int TEST_RUNS = 3;
public static void main(String[] args) throws IOException {
generateTestFile(FILE_PATH, 100_000_000); // 100MB file
// File I/O 측정
long[] ioTimes = new long[TEST_RUNS];
for (int i = 0; i < TEST_RUNS; i++) {
long startTime = System.currentTimeMillis();
fileIO(FILE_PATH, COPY_PATH);
long endTime = System.currentTimeMillis();
ioTimes[i] = endTime - startTime;
}
System.out.println("File I/O 시간: " + Arrays.toString(ioTimes));
// File NIO 측정
long[] nioTimes = new long[TEST_RUNS];
for (int i = 0; i < TEST_RUNS; i++) {
long startTime = System.currentTimeMillis();
fileNIO(FILE_PATH, COPY_PATH);
long endTime = System.currentTimeMillis();
nioTimes[i] = endTime - startTime;
}
System.out.println("File NIO 시간: " + Arrays.toString(nioTimes));
// 평균 시간 측정
double avgLocalTime = Arrays.stream(ioTimes).average().orElse(0);
double avgNioTime = Arrays.stream(nioTimes).average().orElse(0);
System.out.printf("File I/O 평균 걸린 시간: %.2f ms\n", avgLocalTime);
System.out.printf("File NIO 평균 걸린 시간: %.2f ms\n", avgNioTime);
// 누가 몇 퍼센트 빠른지 표기
if (avgLocalTime != 0) {
double percentageDifference = ((avgLocalTime - avgNioTime) / avgLocalTime) * 100;
if (percentageDifference > 0) {
System.out.printf("File NIO가 I/O 보다 %.2f%% 빠릅니다. \n", percentageDifference);
} else {
System.out.printf("File I/O가 NIO 보다 %.2f%% \n", -percentageDifference);
}
} else {
System.out.println("NIO와 IO 걸린시간은 동일합니다.");
}
System.out.println();
}
/**
* IO 테스트할 파일을 생성한다. 파일이 존재하면 생성하지 않고 무시한다.
*
* @param filePath 파일 생성할 위치
* @param size 생성할 파일 사이즈
*/
private static void generateTestFile(String filePath, int size) throws IOException {
File file = new File(filePath);
if (file.exists()) {
return;
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
char[] buffer = new char[BUFFER_SIZE];
Arrays.fill(buffer, 'A');
int written = 0;
while (written < size) {
writer.write(buffer, 0, Math.min(BUFFER_SIZE, size - written));
written += BUFFER_SIZE;
}
}
System.out.println("Test file created.");
}
/**
* IO를 이용해, 주어진 원본 파일로 부터 데이터를 읽어드려 복사할 파일 위치로 붙혀쓴다.
*
* @param srcPath 원본 파일 위치
* @param destPath 복사할 파일 위치
*/
private static void fileIO(String srcPath, String destPath) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath))) {
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
}
}
/**
* NIO를 이용해, 주어진 원본 파일로 부터 데이터를 읽어드려 복사할 파일 위치로 붙혀쓴다.
*
* @param srcPath 원본 파일 위치
* @param destPath 복사할 파일 위치
*/
private static void fileNIO(String srcPath, String destPath) throws IOException {
try (FileChannel srcChannel = FileChannel.open(Paths.get(srcPath), StandardOpenOption.READ);
FileChannel destChannel = FileChannel.open(Paths.get(destPath), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
while (srcChannel.read(buffer) != -1) {
buffer.flip();
while (buffer.hasRemaining()) {
destChannel.write(buffer);
}
buffer.clear();
}
}
}
}Last updated