Windows/MFC

프로그램 수행 속도를 늘리는 팁

aucd29 2013. 10. 2. 17:56
ㄱ. CString : CString 은 메모리를 동적으로 할당하기 때문에 내부적으로 C 런타임
라이브러리르 사용하고 결과적으로는 운영체제 함수를 사용하는것과 같습니다. 따라
서 문자열의 길이가 정해져있는 데이터를 저장할 때에는 CString을 사용하지 않는 것
이 좋습니다. 대신 "const char * "를 사용하시기 바랍니다. 종종 스택에 문자 배열
을 만드는 것도 좋은 방법이 될 수 있습니다. CString 클래스는 문자열을 다루는 데
에 있어서 불필요한 코드를 많이 줄여줍니다. 하지만, CString에서 수행하는 많은 작
업들은 여러분의 수행 속도를 상당히 느리게 할것이라는 점을 명심하시기 바랍니다.
아마도 런타임 라이브러리의 문자열 관련 함수들을 사용하는것이 훨씬 더 빠를 수 있
습니다. 일반적으로 말해서 CString 클래스는 문자열의 길이가 동적으로 변할 경우에
사용하는 것이 좋습니다. 그리고, 결과적으로 메모리의 동적할당과 해제는 항상
overhead 가 있다는 점을 명심하시기 바랍니다.

ㄴ. CArray와 CList : CArray와 CList 클래스는 일반적인 배열에서는 불가능한 배열
의 기능을 제공하는 클래스입니다. 하지만, 만약 여러분의 배열의 최대 길이를 알고
있다면 CArray를 사용하는 대신에 고정된 사이즈의 배열을 사용하는 것이 좋습니다.
굳이 CArray 를 사용해야 한다면 CArray::SetSize 를 사용하여 배열의 최대 길이를 명
시해 준다면 클래스 내부의 불필요한 메모리 재할당 작업을 막을 수 있습니다. 만약
여러분이 SetSize를 사용하지 않는다면, CArray는 배열의 길이가 변할때마다 메모리
를 재할달 할것입니다. 그리고 만약 특정한 형태의 CArray 를 사용하여 여러분의 수행
속도를 빠르게 하고잘 할때에는 template 를 사용하는 방법도 있을 수 있습니다.
CList 클래스는 이중 링크드 리스트를 관리하는 클래스 입니다. 따라서 데이터를 앞
뒤, 혹은 특정 위치에 삽입하는 작업이 빠릅니다. 물론 이러한 작업 역시 순차 검색
을 하기 때문에 리스트의 길이가 길 경우에는 검색 시간에 수행 속도가 낭비될 수 있
습니다. 따라서 여러분의 데이터가 단일 링크드 리스트만으로도 충분하다면 CList 클
래스를 굳이 사용할 필요가 있을지에 대해서 다시 한번 생각해 보셔야 합니다.

ㄷ. IsKindOf : 이 함수는 내부적으로 꽤 많은 함수를 호출하며, 메모리 액세스 작업
또한 상당합니다. (여러분은 MFC 소스 코드를 직접 살펴보실 수 있습니다.) IsKindOf
는 ASSERT 함수의 호출과 같이 debug build 에서는 유용하지만, release build 에서
는 사용하지 않는 것이 좋습니다.

ㄹ. PreTranslateMessage 함수 : 여러분은 윈도우즈의 기본 기능과 다른 키보드 액셀
레이터를 사용하고자 할때 PreTranslateMessage 함수를 사용하여야 합니다. 또한 여러
분은 메세지 펌프안에서 메세지를 처리하기 위해서 이 함수를 사용해야 합니다. 이 함
수를 사용하는 것은 MFC 의 디스패치 메세지 수행 루틴을 바꾸기 위한 수단일 수 있습
니다. 그리고 PreTranslateMessage 를 사용함에 있어서 그 위치를 분명히 할 수 있어
야 합니다. 예를 들어 MainFrame 밑에 있는 특정한 view 로 들어가는 메세지를 가로채
고자 한다면 CMainFrame::PreTranslateMessage 보다는 CView::PreTranslateMessage
를 오버라이드 하시는게 좋습니다. 하지만, PreTranslateMessage 를 사용하여 윈도우
의 디스패치 메세지를 수정하는 작업을 해서는 안됩니다. 이 경우에는 "window
procedures" 나 "MFC message maps" 을 사용하여야 합니다.

ㅁ. OnIdle 함수 : Idle 이벤트는 여러분이 의도하지 않는 시간, 예를 들어
WM_KEYDOWN 과 WM_KEYUP 이벤트 사이, 에 발생할 수 있습니다. 오히려, 타이머가 더
효과적일 수 있습니다. 또한, 여러분의 OnIdle 가 강제적으로 호출되거나 OnIdle 를
오버라이드하여 TRUE 를 리턴하해서는 안됩니다. 만일 TRUE 를 리턴할 경우 당신의
thread가 sleep 상태에 빠지지 않을 수 있기 때문입니다. 다시 한번 언급하지만, 타이
머나 thread 가 보다나은 방법일 것입니다.


Shared 라이브러리

코드의 재사용은 바람직합니다. 하지만, 여러분이 다른 사람의 코드를 사용하려고 한
다면 여러분은 그러한 코드의 어떤 부분이 여러분의 수행 속도에 영향을 미칠 수 있는
가에 대해서 알아야 합니다. 이점을 확인하는 가장 확실한 방법은 소스 코드를 차례대
로 검사해 본다거나 profiler 나 PView 또는 윈도우즈NT Performance monitor를 사용
하여 측정하는 방법입니다.




신중하게 여러개의 힙을 사용하시기 바랍니다. HeapCreate 나 HeapAlloc 을 사용하여
추가적으로 힙을 생성할 수 있으며 관리할 수도 있습니다. 하지만, 여러분의 여러개
의 힙을 사용한다면, 내부적으로 할당된 메모리에 대해서는 관리를 하셔야 합니다.
여러개의 힙을 사용하는 대신에, 여러분은 기본 힙을 감싸고 있는 helper 함수를 사용
하기를 원할 것입니다. 여러분은 여러분의 코드와 기본 힙을 적당히 조율할 수 있는
helper 함수를 만들 수 있습니다. 예를 들어, 만약 여러분이 작은량의 메모리를 자주
할당하고자 한다면 기본 힙의 특정 영역을 여러분의 영역을 할당해 놓고, 그 부분의
메모리를 사용할 수 있을 것입니다. 그리고, 여러분은 힙에서 이루어지는 메모리 할당
을 C 런타임 debug heap routines 로 체크하실 수 있습니다. 여러분은 결과를 Excel에
서 읽을 수 있으며 pivot 테이블을 사용하여 결과값을 볼 수 있습니다. 또한, 윈도우
즈NT performance counter를 사용하여 메모리 할당을 모니터링 할 수도 있습니다.


쓰레드

여러분은 백그라운드로 돌아가는 작업이 필요할 경우 쓰레드를 사용합니다. 물론
idle 이벤트를 효과적으로 사용하는 방법도 좋은 해결책이 될 수 있습니다. 하지만 여
러분은 쓰레드를 사용할때에 동기화나 데드락 같은 문제를 해결해야 하며, 이러한 작
업들을 처리하는 것은 결과적으로 프로그램의 버그를 만들거나 수행 속도를 느리게
할 수 있습니다. 보다 많은 정보를 얻기 위해서는 "Idle Loop Processing"
과 "Multithreading Topics" 를 찾아보시기 바랍니다.


Small Working Set

Smaller working set 는 page fault 가 적은 대신 cache 가 많다는 것을 의미합니다.
즉, 수행 속도면에서 이득을 볼 수 있는 것이죠. Small working set 이라는 것은 그만
큼 locality of reference 가 그만큼 좋다는 의미입니다. 아래의 함수를 사용할 수 있
습니다.
"SetProcessWorkingSetSize", "GetProcessWorkingSetSize".
그리고 Spy++ 이나 PView 와 같은 프로그램으로 working set의 크기를 살펴볼 수 있습
니다.