본문 바로가기
프로그래밍/C++

C++] 파일 입출력시 최적화 방안

by eteo 2025. 4. 17.

 

 

 

C++ 기준 파일 입출력 시 최적화를 통해 속도 개선하는 방법들을 몇가지 소개한다.

 

 

 

1. 큰 버퍼를 미리 할당해서 메모리 재할당 방지

 

std::vector, std::string 등은 내부적으로 동적 메모리를 사용하는데, push_back()이나 append()로 데이터를 계속 집어넣다 보면 사이즈가 커질 때마다 메모리 재할당이 발생해서 성능이 저하될 수 있다.

이를 방지하기 위해 reserve()로 초기에 충분한 용량을 미리 확보해 두면 이후 데이터 추가 시 메모리 재할당 없이 빠르게 처리할 수 있다.

reserve()는 capacity만 늘릴 뿐 size()나 length()에는 영향을 주지 않으며, 선언 시 큰 사이즈로 만든 다음 clear()를 하더라도 capacity는 그대로 유지된다.

 

std::vector<char> data;
data.reserve(1000000);	// 미리 충분한 공간 확보 (size는 0이고 capacity만 커짐)

std::string buffer(10000000);
buffer.clear();			// 내용 비움 (size=0), capacity는 그대로 유지

 

 

 

 

2. 파일은 한 번에 읽기 (디스크 I/O 최소화)

 

while (std::getline(file, line))와 같이 파일을 라인 단위로 읽으면, 내부적으로 디스크 I/O 호출이 반복적으로 발생해서 처리 속도가 느려진다.

이럴 땐 파일을 처음 한 번에 전체를 읽어서 메모리에 로드한 뒤, 라인 단위 처리를 메모리에서 반복하는 게 훨씬 빠르다.

 

// 느린 방식
std::ifstream file("data.csv");
std::string line;
while (std::getline(file, line)) {
    // 처리 (디스크 I/O가 매번 발생하여 느림)
}

// 빠른 방식
std::ifstream file("data.csv");
std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());

std::istringstream ss(buffer);
std::string line;
while (std::getline(ss, line)) {
    // 처리 (디스크 I/O 없음, 메모리 내에서 불러오니 빠름)
}

 

 

 

 

 

3. 파일 출력 시 flush 최소화

 

std::endl manipulator는 내부적으로 줄바꿈과 동시에 flush()를 수행해서 매번 출력 버퍼를 비우기 때문에, 파일 출력 성능이 저하될 수 있다.

std::endl 대신 \n를 써서 ofstream의 내부 버퍼에 계속 쌓아두고, 마지막에 한 번만 flush()를 호출하는 방식이 효율적이다.

 

// 비효율적인 방식 (매번 flush)
for (...) {
    file << data << std::endl;
}

// 효율적인 방식
for (...) {
    file << data << "\n";
}
file.flush();  // 필요한 경우에 한 번 flush