[자바 최적화 연구] if와 switch 조건문 연산 속도 비교 (int)
안녕하세요! 상큼한놈 입니다. 프로그램을 제작하다 보면 가끔은 사용 용도가 중복되는 코드가 많습니다. 무심코 개발 시에 한 가지 방법만 고집하여 프로그래밍하면 개발자는 편할지 몰라도 추후 본인이 원했던 성능에 프로그램이 미치지 못하는 경우도 생길 겁니다. 초보 프로그래머인 저는 간단한 의문점부터 시작하면서 최적화 코드의 연구를 진행하려고 합니다.
이번 연구 내용은 간단합니다. 조건식의 변수가 정수형(int)일 경우 if 조건문과 switch 조건문의 성능 차이를 테스트해보려고 합니다.
테스트 환경
- 운영체제 : MacOS Sierra
- 기종 : Macbook Pro (Retina, 13-inch, Mid 2014)
- JAVA Version : 9.0.4
- IDE Version : Oxygen.2 Release (4.7.2)
테스트 계획
- 0 ~ 9 사이의 정수형 변수를 구분하는 조건문 작성
- 조건문의 가장 낮은 값 0, 중간 값 5(55), else 혹은 default 값 10(100), 0 ~ 10(100)의 랜덤 값을 입력
- 조건문 비교를 1000000회 반복 연산 시간을 확인
클래스 다이어그램
테스트 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package optimization01; public class IfSwitchOptimizationTest { public static void main(String[] args) throws InterruptedException { IfSwitchOptimization iso = new IfSwitchOptimization(); int repeat = 1000000; System.out.println("--입력 값이 0인 경우--"); iso.ifResult(repeat, ()->0); iso.switchResult(repeat, ()->0); System.out.println("--입력 값이 5인 경우--"); iso.ifResult(repeat, ()->5); iso.switchResult(repeat, ()->5); System.out.println("--입력 값이 10인 경우--"); iso.ifResult(repeat, ()->10); iso.switchResult(repeat, ()->10); System.out.println("--랜덤한 숫자가 입력 값일 경우--"); iso.ifResult(repeat, ()->(int)(Math.random()*10)); iso.switchResult(repeat, ()->(int)(Math.random()*10)); } // end of main } // end of class |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package optimization01; public class IfSwitchOptimizationTest2 { public static void main(String[] args) { IfSwitchOptimization iso = new IfSwitchOptimization(); int repeat = 1000000; System.out.println("--입력 값이 0인 경우--"); iso.bigIfResult(repeat, ()->0); iso.bigSwitchResult(repeat, ()->0); System.out.println("--입력 값이 55인 경우--"); iso.bigIfResult(repeat, ()->55); iso.bigSwitchResult(repeat, ()->55); System.out.println("--입력 값이 100인 경우--"); iso.bigIfResult(repeat, ()->100); iso.bigSwitchResult(repeat, ()->100); System.out.println("--랜덤한 숫자가 입력 값일 경우--"); iso.bigIfResult(repeat, ()->(int)(Math.random()*100)); iso.bigSwitchResult(repeat, ()->(int)(Math.random()*100)); } // end of main } // end of class |
1 2 3 4 5 |
package optimization01; public interface VariableRuleGeneratable { public int result(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
package optimization01; public class IfSwitchOptimization { public void ifResult(int repeat, VariableRuleGeneratable value) { int selected = 0; StringBuilder sb = new StringBuilder(); long currentTime = System.currentTimeMillis(); for (int i = 0; i < repeat; i++) { selected = value.result(); if (selected == 0) { sb.append("영"); } else if (selected == 1) { sb.append("일"); } else if (selected == 2) { sb.append("이"); // 중간 생략 } else if (selected == 9) { sb.append("구"); } else { sb.append("무"); } } long resultTime = System.currentTimeMillis() - currentTime; System.out.println(sb.toString()); System.out.println("if 연산 결과 : " + resultTime + "ms"); } // end of ifResult public void switchResult(int repeat, VariableRuleGeneratable value) { int selected = 0; StringBuilder sb = new StringBuilder(); long currentTime = System.currentTimeMillis(); for (int i = 0; i < repeat; i++) { selected = value.result(); switch (selected) { case 0: sb.append("영"); break; case 1: sb.append("일"); break; case 2: sb.append("이"); break; // 중간 생략 case 9: sb.append("구"); break; default: sb.append("무"); } } long resultTime = System.currentTimeMillis() - currentTime; System.out.println(sb.toString()); System.out.println("switch 연산 결과 : " + resultTime + "ms"); } // end of switchResult public void bigIfResult(int repeat, VariableRuleGeneratable value) { int selected = 0; StringBuilder sb = new StringBuilder(); long currentTime = System.currentTimeMillis(); for (int i = 0; i < repeat; i++) { selected = value.result(); if (selected == 0) { sb.append("영"); } else if (selected == 1) { sb.append("일"); } else if (selected == 2) { sb.append("이"); // 중간 생략 } else if (selected == 99) { sb.append("구"); } else { sb.append("무"); } } long resultTime = System.currentTimeMillis() - currentTime; System.out.println(sb.toString()); System.out.println("if 연산 결과 : " + resultTime + "ms"); } // end of bigIfResult public void bigSwitchResult(int repeat, VariableRuleGeneratable value) { int selected = 0; StringBuilder sb = new StringBuilder(); long currentTime = System.currentTimeMillis(); for (int i = 0; i < repeat; i++) { selected = value.result(); switch (selected) { case 0: sb.append("영"); break; case 1: sb.append("일"); break; case 2: sb.append("이"); break; // 중간 생략 case 99: sb.append("구"); break; default: sb.append("무"); } } long resultTime = System.currentTimeMillis() - currentTime; System.out.println(sb.toString()); System.out.println("switch 연산 결과 : " + resultTime + "ms"); } // end of bigSwitchResult } |
테스트 결과
조건문이 10개인 경우
회차 | 이미지 | 조건문 | 입력값 0 | 입력값 5 | 입력값 10 | 입력값 랜덤 |
1 | 🖼 | if | 28ms | 45ms | 65ms | 89ms |
switch | 29ms | 37ms | 52ms | 46ms | ||
2 | 🖼 | if | 53ms | 59ms | 71ms | 115ms |
switch | 37ms | 37ms | 139ms | 56ms | ||
3 | 🖼 | if | 33ms | 51ms | 65ms | 95ms |
switch | 35ms | 46ms | 103ms | 63ms | ||
4 | 🖼 | if | 25ms | 55ms | 71ms | 75ms |
switch | 38ms | 39ms | 97ms | 45ms | ||
평균 | if | 34ms | 52ms | 68ms | 93ms | |
switch | 34ms | 39ms | 97ms | 52ms |
if 조건문의 경우 조건식이 초반에 있을수록 빨랐으며, 조건식이 후반에 있을수록 느려집니다.
switch 구문의 경우 속도의 차이가 있었으나 if 문 처럼 심하진 않았으며 특히 case에 포함되지 않은 값이 나왔을 경우에 극히 느려지는 것을 확인할 수 있었습니다. 허나 랜덤 값이 들어갈 경우 if 조건문과 확연히 구분될 정도로 빨랐습니다.
조건문 10개로는 체감이 되지 않을 수 있음으로 100개도 한번 비교해 봅시다.
조건문이 100개인 경우
회차 | 이미지 | 조건문 | 입력값 0 | 입력값 55 | 입력값 100 | 입력값 랜덤 |
1 | 🖼 | if | 29ms | 85ms | 111ms | 177ms |
switch | 46ms | 56ms | 116ms | 51ms | ||
2 | 🖼 | if | 58ms | 65ms | 110ms | 179ms |
switch | 37ms | 52ms | 116ms | 63ms | ||
3 | 🖼 | if | 32ms | 98ms | 129ms | 200ms |
switch | 60ms | 70ms | 137ms | 57ms | ||
4 | 🖼 | if | 28ms | 83ms | 131ms | 237ms |
switch | 62ms | 58ms | 126ms | 60ms | ||
평균 | if | 36ms | 82ms | 120ms | 198ms | |
switch | 51ms | 59ms | 123ms | 57ms |
if 조건문의 경우 10개와 마찬가지로 조건식이 초반에 있을 수록 빨랐으며 후반에 있으면 심하게 느려졌습니다.
switch 구문 또한 case에 없는 값이 나왔을 경우 급격하게 느려졌으나 랜덤 값에는 if 구문과 확연히 차이 날 정도로 빨랐습니다.
결과
if 구문은 사용자가 자주 사용하는 기능 순서대로 조건문을 써 주면 성능에 큰 도움이 될 것 같습니다. 하지만 사용자가 여러 기능을 유사한 빈도로 사용한다면 switch를 이용하는 것이 더 좋을 듯합니다.
감사합니다.
(오타/코드 상 조언이 있으시면 언제든 댓글 남겨주세요!)