C++ 줄 바꿈 endl과 \n 의 속도 차이

언젠가 대용량 파일을 출력할 일이 있어 코드를 작성하고 테스트할 때는 문제가 없었는데 정작 실제 대용량 파일 출력시 시간이 많이 걸려 한참 코드를 들여다 본 적이 있는데 아주 간단한 문제임을 알고 허탈해 한 적이 있어 간략하게 적어봅니다.

테스트 코드는 아래와 같습니다. 참고로 코드는 visual studio 2019 버젼에서 작성하였습니다.

code
#include <iostream>
#include <fstream>
#include <string>
#include <chrono>

using namespace std;

int main()
{
  ofstream test_file("test.txt");

  chrono::steady_clock count_time;
  auto start = count_time.now();

  for (int i = 1; i < 10000000; i++)
  {
    // 밑의 두 줄을 주석 처리로 바꾸어 가며 실행을 해 본다.
    test_file << to_string(i) << "\n";    // 줄 바꿈으로 "\n"을 사용
    //test_file << to_string(i) << endl;  // 줄 바꿈으로 endl을 사용
  }

  auto end = count_time.now();
  auto loop_time = static_cast<chrono::duration<double>>(end - start);
  cout << "Total process time: " << loop_time.count() << " seconds";  // 경과 시간 출력
  test_file.close();
}

본인의 컴퓨터에서 약 천만줄의 라인을 출력하는데
줄 바꿈으로 "\n"을 사용했을시 약 25초 걸림
줄 바꿈으로 endl을 사용했을시 약 75초 걸림
위와 같이 약 3배의 차이가 나는 것을 간단하게 확인해 볼 수 있음. 차이점은 "\n"은 컴퓨터내 공간을 사용하기만 하고 endl은 flush를 사용해서 컴퓨터 공간을 사용하고 청소해서 비우는 과정을 거쳐서 그런 것임.
즉 다시 말해 밑의 두 줄은 같은 내용을 의미한다고 보시면 됩니다.
cout << endl;
cout << "\n" << flush;
그러므로 endl을 사용하면 버퍼를 비우는 작업(flushing)을 하므로 추가로 시간이 소요되고 사실 버퍼는 꽉 차면 자동적으로 비워지므로 매 작업마다 버퍼를 비울 필요는 없다. 특별히 버퍼를 비워야하는 작업이 필요하면 flush를 명시적으로 사용해서 비우는게 코드를 이해하기도 좋다.