블로그 정리중 발견한 글(2008년 8월 27일 글)

프로젝트를 진행하다보면, 규모와 상관없이 거의 대부분의 경우 if, else나 switch, case문등과 같은 조건문을  사용하게 된다.

이런 조건문들은 프로그램의 논리적인 처리를 위해서 없어서는 안될 문법들이지만, 이들이 너무 많아지거나, 빈번하게 실행되어야 한다면, 다른 방법을 생각해봐야 한다.

소스 코드를 분석할때 다음과 같이 조건문들을 사용하게 된다.

if ~~~

else if~~

else ~~


switch ~~~

case

case

이런 코드는 디버깅이나 코드 분석의 의도로 작성된 경우라면, 굉장히 쉽고 잘 짜여져있으며, 아무런 고민없이 if나 case만 추가하면 되기 때문에유지 보수하기에도 무척 편하다.하지만, 시스템의 성능에 민감한 프로젝트라면 위와 같은 방법을 계속 사용해서는 안되며, 시스템의 응답시간또한 각각에 따라 다르게 나올것이다.

잦은 분기문의 사용은 분기 예측이 가능하지 않은 아키텍쳐의 경우, 생각보다 많은 비용을 요구한다. 이런 연산 비용을 줄이기 위해서는 메모리를 추가적으로 더 사용하면서, 메모리  IO를 최소화 하는 것으로 대체할 수 있다.
즉, 각 조건이나, case들을 처리할때, 하나의 분리된 Memory Table을 사용해서 분기를 고정된 연산비용으로 처리할수 있게 하는 것이다.

예를 들면 다음과 같은 경우이다.
분기해야하는 case가 매우 많은 switch문의 경우 case 내부의 처리하는 부분은 함수를 사용해서 빼낼수 있도록 구성함.

switch(condition)
{

case 1:

break;


case 2:

break;


..........

..........

..........


case N: 
break;
}

위의 코드는 condition의 값으로 각 case에서 각각 정해진 서로 다른 작업들을 하도록 작성되어있다.
이런 경우는 Function Pointer를 사용함으로해서 생각보다 쉽게 해결할 수 있다.
각 case에 해당하는 함수들을 모두 만들어 두고, 하나의 함수 테이블에 등록해놓은 상태에서 바로 호출하는 방법을 사용하거나, 거의 같은 기능을 하는데, condition의 값에 따라 처리하는 값이 차이가 나는 경우라면, 함수만 하나 만들고 그 condition에 의해 처리되어야 하는 값들을 저장하는 Data Table을 만드는 것도 가능하다.

아래는 Function Pointer를 사용하는 방법에 대해서 설명하고 있다.

case를 처리하는 함수들

int case_function1(DWORD dwParam1,DWORD dwParam2)

{

함수 구현

}

int case_function2(DWORD dwParam1,DWORD dwParam2)

{

}

......

......

int case_functionN(DWORD dwParam1,DWORD dwParam2)

{

}

Function pointer Table

static const  int (*case_function[MAX_CASE_NUMS])(DWORD dwParam1,DWORD dwParam2)=

{

case_function1, //이름은 중요하지 않다, 다만 그 순서만 의미가 있을 뿐.(다른 방법으로 enum형을 사용하여 인덱싱 하도록 할수도있다)

case_function2,

.......

.......

case_functionN,

};

실제 case에 대한 처리 부분
case_function[index](dwParam1,dwParam2);

이런작업들을 통해서, 조건문을 모두 제거했다. 물론 방어차원에서, memory fault를 막기 위해, 최대값을 걸러내는 예외처리를 위한 조건문은 추가할 수도 있다.

메모리 구조를 좀 더 효율적으로 설계한다면, 다른 여러가지 case를 처리하여야 하는 경우에 대응할 수 도 있을 것이다. 

저작자 표시
신고

+ Recent posts

티스토리 툴바