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

std::string 간단히 속도 테스트를 해보았다..

by 긱플레이어 2011. 2. 1.

2011-02-18 내용수정 >> 결론 4번
///////////////////////////////////////////////////////////////////////////////


std::string 간단히 속도 테스트를 해보았다..

테스트 방법은
vs 2008 에서 콘솔 프로젝트를 생성하고 설정은 기본으로 만들어진 그대로 진행하였다.
최적화는 기본으로 속도 최적화로 설정 되어있었다..

#include "stdafx.h"

#include 
#include 
#include 
#include 

#pragma comment(lib, "Winmm")

#define printLine(x) std::cout << x << std::endl

class TimeLog
{
public:
	TimeLog( const std::string& msg = std::string() )
		: mLogMessage(msg)
	{
		mStartTime = timeGetTime();
	}
	~TimeLog()
	{
		std::cout
			<< std::setw(6)
			<< timeGetTime() - mStartTime
			<< "(ms) "
			<< mLogMessage
			<< std::endl;
	}

private:
	std::string mLogMessage;
	int mStartTime;
};

std::string retString1() {return "";}
static std::string BlankStr;
std::string retString2() {return BlankStr;}

void main()
{
	DWORD maxCount = 500000000;

	// std::string 초기화 테스트 // "" 를 넣어서 생성.
	{
		TimeLog log("initialize : using(\"\") ");
		for ( DWORD i = 0; i < maxCount; ++i )
		{
			std::string testStr = "";
		}
	}

	// std::string 초기화 테스트 // "" 를 넣지 않고 생성.
	{
		TimeLog log("initialize : default");
		for ( DWORD i = 0; i < maxCount; ++i )
		{
			std::string testStr;
		}
	}
}

위와 같은 코드로 간단히 테스트를 실행해보았다..
우선 위의 코드는 생성자에 대한 속도 테스트..
	maxCount = 200000000;

	// std::string 문자열 대입 속도 테스트
	{
		std::string testStr;
		testStr.resize(1024);

		char* insertString = "abcdefghijklmnABCDEFGHIJKLMN";

		TimeLog log("set data : char*");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			testStr = insertString;
			testStr.erase();
		}
	}

	// std::string 문자열 대입 속도 테스트
	{
		std::string testStr;
		testStr.resize(1024);

		std::string insertString = "abcdefghijklmnABCDEFGHIJKLMN";

		TimeLog log("set data : std::string");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			testStr = insertString;
			testStr.erase();
		}
	}

위의 코드는 데이터를 넣을때의 타입에따른 속도테스트..
	//------------------------------------------------//
	maxCount = 200000000;

	// 함수에서 std::string을 리턴할때 테스트 
	// std::string retString1() {return "";}
	{
		std::string testStr;
		testStr.resize(1024);

		TimeLog log("func return std::string : using(\"\")");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			testStr = retString1();
			testStr.erase();
		}
	}

	// 함수에서 std::string을 리턴할때 테스트 
	// static std::string BlankStr;
	// std::string retString2() {return BlankStr;}
	{
		std::string testStr;
		testStr.resize(1024);

		TimeLog log("func return std::string : static std::string");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			testStr = retString2();
			testStr.erase();
		}
	}

위의 테스트는 함수에서 std::string을 리턴을때
return을 무엇으로 하느냐에 따른 속도 테스트...
	maxCount = 20000000;

	// 문자열 지우기 속도 테스트 // ""
	{
		std::string insertStr;
		insertStr.assign(2048,'a');

		TimeLog log("string clear : using(\"\")");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			std::string testStr = insertStr;
			testStr = "";
		}
	}

	// 문자열 지우기 속도 테스트 // clear
	{
		std::string insertStr;
		insertStr.assign(2048,'a');

		TimeLog log("string clear : clear()");
		for ( DWORD i = 0; i < maxCount; ++i )
		{
			std::string testStr = insertStr;
			testStr.clear();
		}
	}

	// 문자열 지우기 속도 테스트 // erase
	{
		std::string insertStr;
		insertStr.assign(2048,'a');

		TimeLog log("string clear : erase()");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			std::string testStr = insertStr;
			testStr.erase();
		}
	}

std::string내부의 데이터를 지우는 방법에 따른 속도 테스트 ..
	maxCount = 20000000;

	// 문자열 재사용을 위함 문자열 비우기 테스트
	{
		std::string insertStr;
		insertStr.assign(2048,'a');

		std::string testStr;

		TimeLog log("string clear for reuse : using(\"\")");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			testStr = insertStr;
			testStr = "";
		}
	}

	// 문자열 재사용을 위함 문자열 비우기 테스트
	{
		std::string insertStr;
		insertStr.assign(2048,'a');

		std::string testStr;

		TimeLog log("string clear for reuse : clear()");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			testStr = insertStr;
			testStr.clear();
		}
	}

	// 문자열 재사용을 위함 문자열 비우기 테스트
	{
		std::string insertStr;
		insertStr.assign(2048,'a');

		std::string testStr;

		TimeLog log("string clear for reuse : erase()");

		for ( DWORD i = 0; i < maxCount; ++i )
		{
			testStr = insertStr;
			testStr.erase();
		}
	}

위 테스트는...
std::string 객체를 재사용 한다고 생각할때 어떤식의 데이터 초기화가 좋을것인가?



테스트 했던 소스 코드..
아래는 속도 테스트 결과이다...



결과는..
1.  std::string 객체 생성시에는 알아서 초기화를 해주기때문에
     "" << 를 넣어서 해주면 오히려 느려진다..

2. 데이터를 넣을때도 char* 같은 타입으로 넣는것보단 같은 타입인 std::string을 넣는게 빠른다..

3. 함수에서 std::string을 리턴 할때에도 문자열 길이가 0인 문자를 리턴할때
   "" 로 리턴 하는것 보단 글로벌 변수나 static 변수로 미리 만들어 놓은 길이0짜리 std::string 을 리턴하는게 빠르다.

4. std::string 객체 내부의 문자열을 지울때는 "" 로 지우나 erase()로 지우나 별 차이가 없다..
   clear 함수는 내부적으로 erase(begin(),end()) 방식으로 동작하고있다...
   void __CLR_OR_THIS_CALL clear();
   iterator __CLR_OR_THIS_CALL erase(const_iterator _First, const_iterator _Last);
   _Myt& __CLR_OR_THIS_CALL erase(size_type _Off = 0, size_type _Count = npos);
   이 함수는 결과적으로 위와 같이 3개의 함수 호출 순서를 가지므로 erase(); << 이방식보다 비효율적이다.
   클래스의 맴버 객체로 존재하는 std::string들은 메모리 반환(capacity줄이기)을 위해
   std::string().swap(str); 방식으로 지워놓는것도 메모리 상의 효율은 더 좋아보인다. (자주 호출된다면 안쓰는게좋을듯)

5. 같은 std::string 객체 재사용의 관점에서 본다면..
   ""로 지우고 재사용하나 erase로 지우고 하나 별 차이는 없어보인다..
   하지만 바로 재사용을 하는데 clear로 지우고 재사용을 하게되면..
   버퍼의 사이즈가 초기화된 상황에서 다시 버퍼를 늘려야되는 상황이 생기게 되므로 좋지 않겠다..

댓글