C++에서 endl vs \n 성능 차이 알아보기
2025. 2. 12. 07:19ㆍ코딩 도구/기술 & 정보 글 (Tech & Knowledge)
반응형
C++에서 endl vs \n 성능 차이
어느날 처럼 코테 문제를 풀다가 예전에 코테에서는 절대 endl 을 쓰지 마라 라는 말이 기억이나서 출력 부분에서 아무것도 없이 vs \n vs endl 이렇게 출력 시간을 비교해보았는데 시간 차이가 났다.
위에서 부터 endl, \n, x 순서이다.
특히 코딩 테스트나 대량의 데이터를 출력할 때 endl과 \n의 차이가 실행 속도에 큰 영향을 줄 수 있다고 해서 한번 알아보았다.
endl과 \n의 차이
C++에서 줄바꿈을 출력하는 방법은 대표적으로 다음 두 가지가 있다:
- std::endl: 줄바꿈(\n)을 수행한 후, 출력 버퍼를 즉시 비운다(flush).
- '\n': 단순히 줄바꿈을 수행하며, 출력 버퍼를 유지한다.
즉, std::endl은 줄바꿈 후 강제로 버퍼를 비우기 때문에 출력 성능이 떨어질 수 있다. 반면 \n은 버퍼링을 유지하면서 출력하므로 성능이 훨씬 좋다.
예제 코드: endl vs \n 성능 비교
다음은 endl과 \n을 사용했을 때의 실행 속도를 비교하는 코드이다.
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n = 100000;
// endl 사용 (비효율적)
auto start1 = chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++) {
cout << i << endl; // 느림
}
auto end1 = chrono::high_resolution_clock::now();
cout << "Time with endl: "
<< chrono::duration<double>(end1 - start1).count() << "s\n";
// '\n' 사용 (효율적)
auto start2 = chrono::high_resolution_clock::now();
for (int i = 0; i < n; i++) {
cout << i << '\n'; // 빠름
}
auto end2 = chrono::high_resolution_clock::now();
cout << "Time with \\n: "
<< chrono::duration<double>(end2 - start2).count() << "s\n";
return 0;
}
실행 결과 (출력 속도 비교)
끝부분 숫자만 출력되고, endl 테스트 결과가 나오지 않는 현상이 발생한 이유는 출력 버퍼링과 플러싱(flushing) 문제 때문인 것 같다.
원인은 아래와 같다.
원인 분석
- 출력 버퍼링 영향
- std::cout은 기본적으로 내부 버퍼(buffer)를 사용해서 출력을 관리함.
- cout << i << '\n';은 버퍼를 채운 후 한 번에 출력하는 반면, cout << i << endl;은 매번 flush가 발생하여 즉시 출력됨.
- 따라서 터미널이 모든 출력을 바로 처리하지 못하고 마지막 일부 출력만 보임.
- endl 테스트 결과가 사라진 이유
- cout << "Time with endl: " ...이 실행되었을 때, 버퍼가 아직 비워지지 않아서 endl 테스트 결과가 출력되지 않았을 가능성이 큼.
- 특히, 터미널에서는 버퍼링된 출력이 한 번에 표시되거나 특정 크기에 도달할 때만 출력되므로 endl 테스트 부분이 사라질 수 있음.
- 터미널의 출력 제한 문제
- 터미널(콘솔)에는 출력 속도 제한이 있음.
- 100,000줄을 터미널에서 한꺼번에 처리하는 경우, 운영체제가 일부 출력 내용을 버릴 수 있음.
- 그래서 마지막 몇 천 개의 출력만 보이는 것처럼 보일 수 있음.
해결 방법
- 출력을 터미널이 아니라 파일로 저장해서 정확한 결과 확인
- 터미널 대신 파일(ofstream)에 저장하면 운영체제의 터미널 출력 제한을 피할 수 있음.
- 출력 버퍼를 강제 플러시(flush()) 해서 올바른 순서로 출력 확인
- cout.flush();를 추가해서 강제로 출력 내용을 내보내면 출력이 사라지는 문제를 방지할 수 있음.
수정된 코드 (정확한 비교 가능)
#include <bits/stdc++.h>
using namespace std;
using namespace chrono;
const int n = 100000; // 테스트 반복 횟수
void testWithEndl(ofstream &file) {
auto start = high_resolution_clock::now();
for (int i = 0; i < n; i++) {
file << i << endl; // endl 사용 (매번 flush)
}
auto end = high_resolution_clock::now();
cout << "Time with endl: " << duration<double>(end - start).count() << "s\n";
cout.flush(); // 강제 플러시 (터미널에서 사라지는 문제 해결)
}
void testWithNewline(ofstream &file) {
auto start = high_resolution_clock::now();
for (int i = 0; i < n; i++) {
file << i << '\n'; // '\n' 사용 (버퍼링됨)
}
auto end = high_resolution_clock::now();
cout << "Time with \\n: " << duration<double>(end - start).count() << "s\n";
cout.flush(); // 강제 플러시
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
ofstream file1("output_endl.txt");
ofstream file2("output_newline.txt");
cout << "Running tests...\n";
cout.flush(); // 플러시 추가
// endl 테스트
testWithEndl(file1);
file1.close();
// '\n' 테스트
testWithNewline(file2);
file2.close();
cout << "Tests completed.\n";
cout.flush(); // 결과가 사라지는 문제 방지
return 0;
}
코딩 테스트에서는 endl을 절대 사용하지 말자!
코딩 테스트에서는 실행 속도가 중요한데, endl을 사용하면 불필요한 버퍼 flush로 인해 실행 시간이 길어진다. 따라서 항상 \n을 사용하여 출력 속도를 최적화하는 것이 중요하다.
cout.tie(0);을 활용한 입출력 최적화
입출력을 더 빠르게 하고 싶다면, 다음과 같이 cin.tie(0);을 설정하면 된다.
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
이렇게 하면 cin과 cout이 독립적으로 작동하여 입출력 속도를 더욱 향상할 수 있다.
반응형
'코딩 도구 > 기술 & 정보 글 (Tech & Knowledge)' 카테고리의 다른 글
[코딩테스트] BFS에서 배열 크기를 +@로 설정하는 이유 (0) | 2025.02.09 |
---|---|
이스케이프 문자 캐리지 리턴(Carriage Return, \r): 개념과 활용 (0) | 2025.01.23 |
청년 창업과 정부 과제 및 청년지원사업 (1) | 2024.12.30 |
나에게 소프트웨어란: 세상을 변화시키는 도구 (2) | 2024.09.13 |
꼭 알아야 할 TOPCIT 시험의 모든 것 (29) | 2024.05.05 |