본문 바로가기

개발이야기/Effective Java

[Effective Java]예외는 예외적 상황에만 사용하라



아래와 같은 코드를 써서 반복구문(loop)를 돌리는 개발자는 없다.(없어야만 한다)


try{
int i = 0;
while(true)
personArray[i++].addCount();
}catch(ArrayIndexOutOfBoundsException e){
}


문제점이 뭐냐? 크게 3가지로 볼 수 있다.(라고 책에 나와있다.)


1. 예외는 예외적 상황을 위해 설계된 것이므로 JVM수준에서 보면 빠르게 만들 필요가 없다.

2. try-catch 블록안의 코드는 최신JVM의 최적화 기법 중 일부분이 적용되지 않는다.

3. array 내부의 중복 검사가 이루어지지 않는다.


그런데 위 내용에서 추가적으로 책에서 설명한 부분이 있다.


"사실 최신 JVM에서 돌려보면 예외를 통해 구현한 순환문이 표준적 순환문 보다 훨씬 느리다. 

필자의 컴퓨터에서는, 100개 원소를 갖는 배열일 때 두 배 이상 느렸다."


라는 글을 보고 직접 실험해보기로 하였다.


1. for loop

import java.util.Calendar;
public class TestExceptionPerformance {
public static void main(String[] args) {
int count[] = new int[100000];
long startTime = System.currentTimeMillis();
for (int i = 0; i < count.length; i++) { count[i]++; }
long endTime = System.currentTimeMillis();
System.out.println("## 시작시간 : " + new TestExceptionPerformance().formatTime(startTime));
System.out.println("## 종료시간 : " + new TestExceptionPerformance().formatTime(endTime));
System.out.println("## 소요시간(초.0f) : " + (endTime - startTime) / 1000.0f + "초");
}
public String formatTime(long lTime) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(lTime);
return (c.get(Calendar.HOUR_OF_DAY) + "시 " + c.get(Calendar.MINUTE) + "분 " + c.get(Calendar.SECOND) + "."
+ c.get(Calendar.MILLISECOND) + "초");
}
}


2. try-catch loop

import java.util.Calendar;
public class TestExceptionPerformance {
public static void main(String[] args) {
int count[] = new int[100000];
long startTime = System.currentTimeMillis();
try {
int i = 0;
while (true)
count[i++]++;
} catch (ArrayIndexOutOfBoundsException e) {
}
long endTime = System.currentTimeMillis();
System.out.println("## 시작시간 : " + new TestExceptionPerformance().formatTime(startTime));
System.out.println("## 종료시간 : " + new TestExceptionPerformance().formatTime(endTime));
System.out.println("## 소요시간(초.0f) : " + (endTime - startTime) / 1000.0f + "초");
}
public String formatTime(long lTime) {
Calendar c = Calendar.getInstance();
c.setTimeInMillis(lTime);
return (c.get(Calendar.HOUR_OF_DAY) + "시 " + c.get(Calendar.MINUTE) + "분 " + c.get(Calendar.SECOND) + "."
+ c.get(Calendar.MILLISECOND) + "초");
}
}



실험 결과는 아래와 같았다.


1. for loop


2. try-catch loop



이유는 모르겠지만 책의 설명과는 다르게 성능 상 차이가 없는 것으로 보인다.


그러나 성능상 차이가 없다고 평상시의 제어흐름(ex. if, loop, etc)에 이용해서는 안된다


결론 : 예외는 예외적 상황에만 사용하라


End of Document

반응형