본문 바로가기
개발/C C++

C++ 성능이야기 – MFC CString 인자로 사용하기

by esstory 2007. 4. 27.

MFC로 어플리케이션을 만들 경우 CString 에 대한 의존도가 상당히 높습니다. 하지만 CString 을 남용함으로써 성능 저하를 일으키는 경우가 많은데 오늘은 그 중 CString 문자열을 함수로 전달할 때 발생하는 성능관련 이슈를 확인하려고 합니다

 

1.     테스트의 목적
문자열 함수 처리에 많이 사용되는 CString 을 다른 함수로 전달 할 경우 가장 좋은 성능을 가진 함수 인자 선언 TYPE 을 찾기 위함.

 

2.     테스트 환경

1)     컴파일러 - VISUAL STUDIO .NET 2005

2)     PC 사양 - Pentium® D CPU 3.19GHz, 2GB RAM

 

3.     테스트 코드 인자로 들어온 텍스트를 DUMMY CString 할당하고 간단한 자연수 연산을 한 뒤 리턴 하는 함수

// 인자로CString 레퍼런스전달

int CPerfTestDlg::testObject(const CString& sText)

{

           CString sData = sText;

           //sData.MakeUpper();

           int i = 10 * 100;

           return i;

}

 

4.     테스트용 함수선언

CASE

방법

사용 함수 헤더

호출방식

1

CString Reference 사용

int testObject(const CString& sText);

CString sTest = "abcd";

int nRet = testObject(sTest);

2

CString 객체 전달

int testObject2(CString sText);

CString sTest = "abcd";

int nRet = testObject(sTest);

3

CString à const char 로 변환

int testObject3(const char* lpText);

CString sTest = "abcd";

int nRet = testObject(sTest);

4

상수를 const char 사용

int testObject3(const char* lpText);

nRet = testObject3("abcd");

 

5.     테스트 결과(각 함수를 1,000,000번 호출)

CASE

방법

결과(ms)

성능차

1

CString Reference 사용

68

100%

2

CString 객체 전달

140

205.88%

3

CString à const char 로 변환

411

604.41%

4

상수를 const char 사용

412

605.88%

 

6.     결론

1)     CString 을 함수의 인자로 전달 할 경우 Reference Point 로 전달하는 것이 가장 빠름

2)     CString const char 로 변환하는 작업은 상당히 많은 시간이 걸리며 CString 을 값으로 전달하는 방법 ‘2’번보다 오히려 성능이 떨어짐(const char* 로 변환하기 위한 operation에 상당한 시간이 걸림을 확인)

3)     대부분의 함수 사용하는 곳에서 CString 문자열을 넘긴다고 가정할 경우 const char* 를 인자로 사용하기 보다 CString* CString&를 사용하는 것이 성능향상에 도움이 됨(일반적인 문자열 전달은 const char* 가 맞지만 현실과 성능은 늘 괴리가 있다 ㅠ_)

 

7.     부록(?) – 실제 코드

void CPerfTestDlg::OnBnClickedButton2()

{

           // TODO: Add your control notification handler code here

           char szText[100];

           DWORD dwStartTime = timeGetTime();

           int nRet;

           CString sTest = "abcd";

           for (int i = 0; i < 1000000; i++)

           {

                     nRet = testObject(sTest);

           }

           sprintf_s(szText, sizeof(szText),"testObject Ellapsed->%ld",timeGetTime() - dwStartTime);

           m_ResultList.AddString(szText);

 

           dwStartTime = timeGetTime();

           for (int i = 0; i < 1000000; i++)

           {

                     nRet = testObject2(sTest);

           }

           sprintf_s(szText, sizeof(szText),"testObject2 Ellapsed->%ld",timeGetTime() - dwStartTime);

           m_ResultList.AddString(szText);

 

           dwStartTime = timeGetTime();

           for (int i = 0; i < 1000000; i++)

           {

                     nRet = testObject3(sTest);

           }

           sprintf_s(szText, sizeof(szText),"testObject3 Ellapsed->%ld",timeGetTime() - dwStartTime);

           m_ResultList.AddString(szText);

 

           dwStartTime = timeGetTime();

           for (int i = 0; i < 1000000; i++)

           {

                     nRet = testObject3("abcd");

           }

           sprintf_s(szText, sizeof(szText),"testObject5 Ellapsed->%ld",timeGetTime() - dwStartTime);

           m_ResultList.AddString(szText);

 

}

 

int CPerfTestDlg::testObject(const CString& sText)

{

           CString sData = sText;

           int i = 10 * 100;

           return i;

}

int CPerfTestDlg::testObject2(CString sText)

{

           CString sData = sText;

           int i = 10 * 100;

           return i;

}

int CPerfTestDlg::testObject3(const char* lpText)

{

           CString sData = lpText;

           int i = 10 * 100;

           return i;

 

 

댓글