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
'프로그래밍 > C++' 카테고리의 다른 글
C++] explicit 키워드 (0) | 2025.05.06 |
---|---|
C++ ] uint8_t, int_8t를 스트림 연산자(<<)로 출력할 때의 문제점 (0) | 2025.04.18 |
C++ ] <random> 헤더 사용 난수 생성 (0) | 2024.12.03 |
C++ ] CLI Loading indicator와 Progress bar (0) | 2024.10.28 |
C++ ] 가변 인자 템플릿(Variadic Templates) 활용 (0) | 2024.09.02 |