회사 동기중 한명이 ifstream의 getline이 fgets보다 성능이 좋다는 썰을 풀길래 이건 무슨 신박한 개소리인가 싶어 간단히 속도 테스트를 해보았습니다. 테스트 환경은 윈10 64bit, 약 14M 정도의 로그 데이터파일을 기준으로 짜둠!


..일단 결론부터 말하면, ifstream은 쓸 것이 못 됩니다. 수백메가도 아닌 단 몇천줄 로그파일 읽는데에도 시간이 훨씬 차이가 납니다.





1) getline()으로 직접 읽기. 버퍼를 지정하고 직접 넘겨주기에 ifstream 중에서 그나마 성증이 좋음


void test_ifstream1() {
	std::ifstream inFile;
	inFile.open(TEST_FILE);

	if (!inFile.is_open()) exit(1);

	char buf[512];
	while (!inFile.getline(buf, sizeof(buf)).eof()) {

	}
}



2) istreambuf_iterator 사용. 모든 내용은 vector<char>형태로 저장. 나름 버퍼를 사용하는구나 싶어 성능이 좋겠다 생각했지만, 정반대이다.


void test_ifstream2() { std::ifstream inFile; inFile.open(TEST_FILE); if (!inFile.is_open()) exit(1); std::istreambuf_iterator<char> begin(inFile); std::istreambuf_iterator<char> end; std::vector<char> contents(begin, end); }



3) fopen()과 fread()를 사용. 한꺼번에 512byte 정도를 읽어오며, 딱 한 줄씩 읽어오지는 않는다. ifstream을 사용할때보다 약 7배이상 성능이 좋음.

   대신, 한 줄씩 읽어서 처리할 경우 문자별 매칭을 수행해야하는 번거로움이 생긴다.


void test_osfile1() {
    FILE *fp = fopen(TEST_FILE, "r");

    if (NULL == fp) exit(1);

    char buf[512];

    size_t len = 0;
    while (!feof(fp)) {
        len = fread(buf, sizeof(buf[0]), sizeof(buf)/sizeof(buf[0]), fp);
    }
    fclose(fp);
}



4) fgets() 함수. 위의 fread보단 시간이 약-간 더 걸렸다.


void FREAD_TEST() {
	FILE *fp = fopen(TEST_FILE, "rb");
	if (NULL == fp)
		exit(1);

	char buf[BUF_SIZE] = { 0, };

	char buf[BUF_SIZE] = { 0, };
	while (NULL != fgets(buf, sizeof(buf), fp)) {}

	fclose(fp);
}




normal read에선 크게는 7000msec 까지 차이가 나더이다. 이는 엄청난 수치죠. binary read라면 워낙 빠르기에 차이가 미미할 수도 있지만..


사실 여러 운영체제에 포팅하는 경우 이식성을 높이기 위해선 ifstream을 쓰는 것이 가장 좋을수도 있습니다. 하지만 성능이 문제라면.. 다른 공통으로 사용할 수 있는 라이브러리는 찾는게 방안일 수도 있겠네요. 안정성과 검증을 해야하는 문제도 있고..


하지만 fopen()은 공통 c라이브러리이기 때문에 대부분 호환 가능해서 이식성에 어려움은 없습니다. 문제는 기존 C++의 stl과 연동이 자연스럽지 않기에 이를 어떻게 풀어야 하는가. 즉, 해야할 일들이 많이 생기게는 되겠네요 = _=


어쨌든! 단순 성능비교를 할땐 fread()의 성능이 압도적인걸로!


+ Recent posts