Java Buffer I/O와 Scanner, Sysout 입출력 시간 비교

Java Buffer I/O와 Scanner, Sysout 입출력 시간 비교

Buffer I/O와 Scanner, Sysout 시간 차이

1. Sysout & Scanner

1
System.out.println("Hello World");
1
2
3
4
import java.util.Scanner;
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
scanner.close();

자바를 입문하면 먼저 배우게 되는 입출력 방식이다. 이 방식은 아주 기초적이면서도 간단하다.

하지만 알고리즘 문제를 풀다보면 이것들로 인해서 시간 초과가 되는 경우도 있다.

2. BufferedWriter & BufferedReader

많이들 이러한 상황에서 Buffer I/O를 사용하라고 한다. 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.*;

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BuffetedWriter(new OutputStreamWriter(System.out));
try{
String input = br.readLine();
bw.write(input);
bw.flush();
bw.close();
br.close();
}catch(IOException e){
System.out.println(e.getMessage());
}

육안으로만 봐도 이전의 입출력 방식보다 훨씬 입력해야하는 코드가 훨씬 많아진다.

하지만 Buffer를 이용하면서 아주 빠른 입출력 시간을 보여주게 된다.

3. BufferedWriter와 System.out.println() 비교

각각 for문을 사용하여 10만번 실행시켰고 호기심에 print()도 포함시켜서 비교해 보았다.

테스트 결과
비교결과

print()와 println()간의 유의미한 차이도 있었지만 bw.write()가 압도적으로 빠른 속도를 보였다.

차이점은 print()와 println()는 반복문이 돌면서 그때그때 즉시 출력해준다면

bw.write()는 buffer에 모아두었다가 버퍼를 비워주면서 한꺼번에 출력시켜준다.

이 과정에서 시간 차이가 생긴다.

이와 별개로 print()와 println()간 차이는 개행문자에 의한 개행과 메소드에 의한 개행의 시간 차이로 보인다.

유사한 이유로는 C++에서 endl의 개행와 개행문자의 개행 간 시간 차이가 난다고 한다.

테스트 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Main {
public static void main(String[] args) throws Exception {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int testCount = 100000;
long start = System.currentTimeMillis();
for (int i = 0; i < testCount; i++) {
System.out.print(i + "\n");
}
long end = System.currentTimeMillis();
double print_time = (end - start) / 1000.0;

start = System.currentTimeMillis();
for (int i = 0; i < testCount; i++) {
System.out.println(i);
}
end = System.currentTimeMillis();
double println_time = (end - start) / 1000.0;

start = System.currentTimeMillis();
for (int i = 0; i < testCount; i++) {
bw.write(i + "\n");
}
end = System.currentTimeMillis();
double bw_time = (end - start) / 1000.0;
bw.write("총 실행 횟수 : " + testCount + "회\n");
bw.write("print() 실행시간 : " + print_time + "초\n");
bw.write("println() 실행시간 : " + println_time + "초\n");
bw.write("BufferedWriter 실행시간 : " + bw_time + "초\n");
bw.flush();
bw.close();
}
}

4. BufferedReader와 Scanner 비교

이와 같이 각각 for문을 사용하여 10만번 실행시켜 비교하였다.

테스트 결과
비교결과

이전의 bw.write()와 println()와는 차원이 다른 차이가 나왔다.

알고리즘 채점 과정에서 수많은 테스트 케이스를 입력받게 되는데 입력 받은 양이 방대해질 경우
입력 받다가 시간 초과가 생길 수도 있다는 뜻이다.

테스트 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.io.*;
import java.util.*;

public class Main {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int testCount = 100000;
scanner.nextLine();
long start = System.currentTimeMillis();
int temp = 0;
for (int i = 0; i < testCount; i++) {
temp = scanner.nextInt();
}
long end = System.currentTimeMillis();
double scanner_time = (end - start) / 1000.0;
scanner.close();

br.readLine();
start = System.currentTimeMillis();
for (int i = 0; i < testCount; i++) {
temp = Integer.parseInt(br.readLine());
}
end = System.currentTimeMillis();
double br_time = (end - start) / 1000.0;
bw.write("총 실행 횟수 : " + testCount + "회\n");
bw.write("println() 실행시간 : " + scanner_time + "초\n");
bw.write("BufferedWriter 실행시간 : " + br_time + "초\n");
bw.flush();
bw.close();
}
}

5. 결론

알고리즘과 같이 방대한 양의 입출력이 필요할 땐 Buffer I/O를 활용하자.

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×