아래와 같은 코드를 써서 반복구문(loop)를 돌리는 개발자는 없다.(없어야만 한다)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
반응형
'개발이야기 > Effective Java' 카테고리의 다른 글
[Effective Java]실패 원자성 달성을 위해 노력하라 (0) | 2017.03.04 |
---|---|
[Effective Java]어떤 오류인지를 드러내는 정보를 상세한 메시지에 담으라 (0) | 2017.03.04 |
[Effective Java]메서드에서 던져지는 모든 예외에 대해 문서를 남겨라 (0) | 2017.03.04 |
[Effective Java]표준 예외를 사용하라 (0) | 2017.03.04 |
[Effective Java]불필요한 점검지정 예외 사용은 피하라 (0) | 2017.02.23 |
[Effective Java]생성자 인자가 많을 때는 Builder 패턴 적용을 고려하라. (1) | 2017.02.20 |