일반적으로 경과 시간(elapsed time) 또는 실행 시간(execution time)이란 하나의 작업이 시작 지점부터 종료 지점까지 걸린 시간을 의미합니다. 성능 최적화나 병목 지점 분석을 위해서는 코드의 실행 시간을 정확히 측정하는 것이 매우 중요합니다. Java에서는 다양한 방법으로 경과 시간을 측정할 수 있습니다.
Java에서 경과 시간을 측정하는 주요 방법
- System.currentTimeMillis() : 현재 시간을 밀리초(millisecond) 단위로 반환합니다. 메서드 실행 전후의 시간 값 차이를 구하면 해당 메서드의 경과 시간을 알 수 있습니다.
- System.nanoTime() : 현재 시간을 나노초(nanosecond) 단위로 반환합니다. 실행 전후의 시간 차이를 계산하며, currentTimeMillis()보다 더 정밀한 측정이 가능합니다.
- Instant.now() + Duration.between() : Instant 클래스의 now() 메서드로 현재 시각을 얻고, Duration.between() 메서드로 두 시점 사이의 차이를 계산하여 실행 시간을 구할 수 있습니다.
- Apache Commons StopWatch : Apache Commons 라이브러리에서 제공하는 StopWatch 클래스를 사용하면 start(), stop(), getTime() 메서드로 간편하게 실행 시간을 측정할 수 있습니다.
- Date.getTime() : java.util.Date 클래스의 getTime() 메서드는 현재 시간을 반환합니다. 실행 전후의 시간 차이로 경과 시간을 구할 수 있습니다.
- Calendar.getInstance().getTime().getTime() : Calendar 클래스로도 현재 시간을 가져올 수 있으며, 시간 차이를 계산하여 경과 시간을 구할 수 있습니다.
예제 1: currentTimeMillis() 메서드 사용
public class Example {
public void test(){
int num = 0;
for(int i=0; i<=50; i++){
num = num+i;
System.out.print(num+", ");
}
}
public static void main(String args[]){
// 시작 시간
long begin = System.currentTimeMillis();
// 테스트 메서드 실행
new Example().test();
// 종료 시간
long end = System.currentTimeMillis();
long time = end-begin;
System.out.println();
System.out.println("Elapsed Time: "+time +" milli seconds");
}
}실행 결과
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, Elapsed Time: 4 milli seconds
예제 2: nanoTime() 메서드 사용
나노초 단위의 정밀한 측정이 필요하다면 nanoTime() 메서드를 사용하는 것이 좋습니다.
public class Example {
public void test(){
int num = 0;
for(int i=0; i<=50; i++){
num = num+i;
System.out.print(num+", ");
}
}
public static void main(String args[]){
// 시작 시간
long begin = System.nanoTime();
// 테스트 메서드 실행
new Example().test();
// 종료 시간
long end = System.nanoTime();
long time = end-begin;
System.out.println();
System.out.println("Elapsed Time: "+time);
}
}실행 결과
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, Elapsed Time: 1530200
예제 3: Instant 클래스 사용
Java 8부터 도입된 java.time API의 Instant 클래스와 Duration 클래스를 활용하면 더욱 직관적으로 시간을 측정할 수 있습니다.
import java.time.Duration;
import java.time.Instant;
public class Example {
public void test(){
int num = 0;
for(int i=0; i<=50; i++){
num = num+i;
System.out.print(num+", ");
}
}
public static void main(String args[]) {
// 시작 시간
Instant start = Instant.now();
new Example().test();
// 종료 시간
Instant end = Instant.now();
long time = Duration.between(start, end).toMillis();
System.out.println();
System.out.println(time+" Milli seconds");
}
}실행 결과
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, 3 Milli seconds
예제 4: StopWatch 클래스 사용
Apache Commons Lang 라이브러리의 StopWatch 클래스를 사용하면 스톱워치를 조작하듯 직관적으로 시간을 측정할 수 있습니다. 라이브러리를 프로젝트에 추가해야 한다는 점에 유의하세요.
import org.apache.commons.lang3.time.StopWatch;
public class Example {
public void test(){
int num = 0;
for(int i=0; i<=50; i++){
num = num+i;
System.out.print(num+", ");
}
}
public static void main(String args[]) {
// StopWatch 객체 생성
StopWatch obj = new StopWatch();
// 측정 시작
obj.start();
new Example().test();
// 측정 종료
obj.stop();
System.out.println();
System.out.println("Elapsed Time: "+obj.getTime() +" milli seconds");
}
}실행 결과
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, Elapsed Time: 1 milli seconds
예제 5: Date 클래스의 getTime() 메서드 사용
import java.util.Date;
public class Demo{
public void test(){
int num = 0;
for(int i=0; i<=50; i++){
num = num+i;
System.out.print(num+", ");
}
}
public static void main(String[] args) {
long startTime = new Date().getTime();
new Demo().test();
long endTime = new Date().getTime();
long time = endTime - startTime;
System.out.println("Execution time: " + time);
}
}실행 결과
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, Execution time: 5
예제 6: Calendar 클래스 사용
import java.util.Calendar;
public class Demo{
public void test(){
int num = 0;
for(int i=0; i<=50; i++){
num = num+i;
System.out.print(num+", ");
}
}
public static void main(String[] args) throws InterruptedException {
long startTime = Calendar.getInstance().getTime().getTime();
new Demo().test();
long endTime = Calendar.getInstance().getTime().getTime();
long time = endTime - startTime;
System.out.println("Execution time: " + time);
}
}실행 결과
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, Execution time: 20
어떤 방법을 선택해야 할까?
간단한 성능 측정에는 System.nanoTime() 또는 System.currentTimeMillis()가 가장 널리 사용되며, 외부 라이브러리 의존성이 없다는 장점이 있습니다. Java 8 이상 환경이라면 Instant와 Duration을 활용하는 방식이 코드 가독성 면에서 우수하고, 여러 구간의 시간을 측정해야 하는 경우에는 Apache Commons StopWatch가 편리합니다. 반면 Date와 Calendar는 레거시 코드에서 주로 사용되므로 새로운 프로젝트에서는 java.time API 사용을 권장합니다.