반응형

개발과정에 특정 값에 대한 특정 Action이 필요할 때, 흔히 if문과 switch문을 사용한다.

 

private void somethingIf(int value) {
    if (value > 0) {
    	// do something
    }
}

private void somethingSwitch(int value) {
    switch(value) {
        default:
        // do something
    }
}

 

위의 두 구문의 경우, 대부분 개발자마다 각기 다르게 본인의 취향에 따라 코드를 작성하고 있다.

 

아마 대부분 if문과 switch문의 동작구조에 대해 별다른 고민없이 사용하지 않을까 한다.

그래서 이번 포스팅에서는 if문과 switch문의 동작구조에 대해 알아보고 어떻게 쓰면 더 효율적인 코딩이 가능할지에 대해 고민해보고자 한다.

 

 

if 문

Branch statement의 대표주자.

레지스터 2개 값 혹은 레지스터와 값 비교 후 특정 메모리 번지로 이동할 지 결정.

따져야 하는 조건이 많아질수록 연산량이 늘어난다.

 

 

 

 

switch 문

Jump Statement의 대표주자.

따져야하는 조건이 많을수록 유리.

점프 테이블 생성에 오버헤드 발생 가능성이 있다.

case의 개수가 4개 이하면 jump table 미 생성. 4개 이상일 경우 jump table 생성

jump table의 크기는 가장 큰 값 - 가장 작은 값 으로 결정되나

중간에 순차 증가가 아닌 경우 더 많은 메모리 사용한다.

ex) case 1, case 2, case 3, case 4 (메모리크기 4)

ex ) case 1, case2, case3, case 10 (메모리크기 10)

 

 

 

정리하며.....

따져야 하는 조건이 4개 이하일 때는 if문, 4개 이상일때는 switch문을 사용하는 것이 유리하나

switch문의 경우, 점프 테이블 생성에 오버헤드 발생 가능성이 있기에 성능보다 메모리 사용량이 중요할 경우 simplify 된 if문을 통해 처리하는 것이 중요하다.

 

 

 

정말 차이가 있을까?

정말 차이가 있는지 궁금해서 Android 단말에서 돌려 보았다.

 

조건은 다음과 같았다.

비교 조건문이 4개 이상

switch 구문의 case문이 연속된 값이 아닌 비 연속적 데이터와 다양한 range의 값 설정.

테스트 측정은 시간으로 진행.

 

private void callTest() {
    checkBranchState(101);
    checkJumpState(101);
}
 
private void checkBranchState(int value) {
    Log.e("JAYJ","start state : "+ System.currentTimeMillis());
    if (value == 0) {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    } else if (value == 1) {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    } else if (value == 2) {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    } else if (value == 100) {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    } else if (value == 101) {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    } else if (value == 102) {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    } else if (value == 103) {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    } else {
        Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
    }
    Log.e("JAYJ","end state : "+ System.currentTimeMillis());
}
 
private void checkJumpState(int value) {
    Log.e("JAYJ","start state : "+ System.currentTimeMillis());
    switch (value) {
        case 100:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
        case 101:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
        case 102:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
        case 103:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
        case 0:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
        case 1:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
        case 2:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
        default:
            Log.e("JAYJ","target matched : "+ System.currentTimeMillis());
            break;
    }
    Log.e("JAYJ","end state : "+ System.currentTimeMillis());
}

 

 

결과

2019-03-31 23:12:01.100 13520-13520/com.ktops.myapplication E/JAYJ: Branch Statement start state : 1554041521100
2019-03-31 23:12:01.101 13520-13520/com.ktops.myapplication E/JAYJ: Branch Statement target matched : 1554041521101
2019-03-31 23:12:01.101 13520-13520/com.ktops.myapplication E/JAYJ: Branch Statement end state : 1554041521101
2019-03-31 23:12:01.101 13520-13520/com.ktops.myapplication E/JAYJ: Jump Statement start state : 1554041521101
2019-03-31 23:12:01.101 13520-13520/com.ktops.myapplication E/JAYJ: Jump Statement target matched : 1554041521101
2019-03-31 23:12:01.101 13520-13520/com.ktops.myapplication E/JAYJ: Jump Statement end state : 1554041521101



2019-03-31 23:12:24.903 15630-15630/? E/JAYJ: Branch Statement start state : 1554041544903
2019-03-31 23:12:24.903 15630-15630/? E/JAYJ: Branch Statement target matched : 1554041544903
2019-03-31 23:12:24.903 15630-15630/? E/JAYJ: Branch Statement end state : 1554041544903
2019-03-31 23:12:24.903 15630-15630/? E/JAYJ: Jump Statement start state : 1554041544903
2019-03-31 23:12:24.903 15630-15630/? E/JAYJ: Jump Statement target matched : 1554041544903
2019-03-31 23:12:24.903 15630-15630/? E/JAYJ: Jump Statement end state : 1554041544903



2019-03-31 23:12:52.415 15981-15981/? E/JAYJ: Branch Statement start state : 1554041572415
2019-03-31 23:12:52.415 15981-15981/? E/JAYJ: Branch Statement target matched : 1554041572415
2019-03-31 23:12:52.415 15981-15981/? E/JAYJ: Branch Statement end state : 1554041572415
2019-03-31 23:12:52.415 15981-15981/? E/JAYJ: Jump Statement start state : 1554041572415
2019-03-31 23:12:52.415 15981-15981/? E/JAYJ: Jump Statement target matched : 1554041572415
2019-03-31 23:12:52.415 15981-15981/? E/JAYJ: Jump Statement end state : 1554041572415

 

 

 

마치며...

테스트 코드를 통해 수행한 결과, 본 테스트에서는 switch문 대비 if문의 성능저하는 발견하지 못했다.

물론 각 분기문에서 발생되는 파생 action이 없이 단순 로깅 정도의 action만 수행하였기에 큰 차이가 없었을 수도 있다.

 

이번 주제를 통해 정리된 내용은 다음과 같다.

 

  • 케이스가 정의되지 않은 경우, if문으로 정의힌다.
  • if문이든 switch문이든 매개변수의 경우, 사전에 null체크가 완료된 데이터를 인입한다.
  • switch문에 default구문은 기본 action을 정의하지 않고, Exception 케이스에 대해 정의한다.
반응형

+ Recent posts