Java 프로그램 실행 속도를 측정하는 방법


85

Java 프로그램 실행 시간은 어떻게됩니까? 이 작업을 수행하기 위해 어떤 클래스를 사용해야하는지 잘 모르겠습니다.

나는 다음과 같은 것을 찾고 있습니다.

// Some timer starts here
for (int i = 0; i < length; i++) {
  // Do something
}
// End timer here

System.out.println("Total execution time: " + totalExecutionTime);

답변:


139
final long startTime = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
  // Do something
}
final long endTime = System.currentTimeMillis();

System.out.println("Total execution time: " + (endTime - startTime));

2
정말 실제로 nanoTime을해야한다
— 유진

6
nanoTime이 아니어야합니다. rhu의 대답을 참조하십시오.
— fabspro 2013

4
여기서 "파이널"을 사용한 특별한 이유가 있습니까? 해당 키워드를 삭제하면 어떻게됩니까?
— dijxtra

9
@dijxtra using final은 실수로 할당 할 수 없다는 장점이 있습니다 (익명 클래스 액세스 등의 다른 장점도 있음). 이 코드에서는 차이가 없습니다. 모든 것을 만들고 필요한 경우 final에만 final단일화하는 것은 매우 일반적인 관행 입니다.
— wchargin 2013-08-28

1
테스트 할 코드는 시간 측정과 함께 여러 번 실행되어야하며 첫 번째 결과는 삭제되어야합니다. 첫 번째는 클래스 로딩 시간 등을 포함 할 것입니다. 여러 번 실행하면 더 유용하고 신뢰할 수있는 평균을 얻을 수 있습니다.
— Arun Ramakrishnan

34

System#nanoTime()멀티 코어 CPU에서 경과 시간을 기록하기 위해 안정적으로 사용할 수없는 몇 가지 문제가 있습니다. 각 코어는 자체 TSC ( Time Stamp Counter )를 유지합니다 .이 카운터는 나노 시간을 얻는 데 사용됩니다 (실제로는 CPU 부팅 이후의 틱 수).

따라서 OS가 코어를 동기화 상태로 유지하기 위해 일부 TSC 시간 왜곡을 수행하지 않는 한, 스레드가 초기 시간 판독 값을 취할 때 한 코어에서 예약 된 다음 다른 코어로 전환되면 상대적 시간이 산발적으로 뒤로 점프하는 것처럼 보일 수 있습니다. 그리고 앞으로.

나는 얼마 전에 AMD / Solaris에서 이것을 관찰했는데, 두 타이밍 포인트 사이의 경과 시간이 때때로 음수 값이나 예기치 않게 큰 양수로 돌아 오는 경우가있었습니다. AMD PowerNow!를 강제하는 데 필요한 Solaris 커널 패치와 BIOS 설정이있었습니다. 그것을 해결하는 것처럼 보였다.

또한 System#nanoTime()VirtualBox 환경에서 Java 를 사용할 때 지금까지 수정되지 않은 버그 (AFAIK)가 있습니다. java.util.concurrency패키지의 대부분이 나노 시간에 의존 하기 때문에 모든 종류의 기괴한 간헐적 스레딩 문제를 야기합니다 .

또한보십시오:

System.nanoTime ()은 완전히 쓸모가 없습니까? http://vbox.innotek.de/pipermail/vbox-trac/2010-January/135631.html


9

현재 시스템 시간 (밀리 초)을 얻습니다.

final long startTime = System.currentTimeMillis();

그런 다음 수행 할 작업을 수행합니다.

for (int i = 0; i < length; i++) {
  // Do something
}

그런 다음 소요 된 시간을 확인합니다.

final long elapsedTimeMillis = System.currentTimeMillis() - startTime;

BalusC의 대답도 정확합니다. 필요한 타이머 해상도와 타이밍이 필요한 이유에 따라 다릅니다.
— Jonathan Feinberg

9

사용할 수 있습니다 System#nanoTime(). 실행 전후에 그것을 얻고 수학을하십시오. System#currentTimeMillis()정밀도가 더 높기 때문에 위에서 선호 됩니다. 사용하는 하드웨어 및 플랫폼에 따라 경과 시간에 잘못된 간격이 발생할 수 있습니다. Windows에서 Core2Duo를 사용하면 약 0 ~ 15ms 사이에는 실제로 아무것도 계산할 수 없습니다.

고급 도구는 프로파일 러 입니다.


Windows의 타이머는 기본적으로 특별히 좋은 해상도를 가지고 있지 않습니다. 이 인 고성능 타이머도하지만 훨씬 더 어렵다 C에서도 사용하고 자바 (AFAIK)는 JNI없이 해커의 수준이 썽크이 저에 대한 액세스를 제공하지 않습니다.
— Donal Fellows

1
nanoTime()하나의 문제가 있습니다 (적어도 Windows에서는). 타임 스탬프는 프로세서 코어에 따라 다릅니다. 한 코어에는 "시작"타임 스탬프가 있고 다른 코어에는 "중지"타임 스탬프가 있기 때문에 실행 시간이 음수 인 프로그램이 있습니다.
— gustafc 2010

3

간단한 작업의 경우 System.currentTimeMillis () 가 작동 할 수 있습니다.

실제로 내 IDE가 설정되어 "t0"을 입력하면 다음 줄이 생성됩니다.

final long t0 = System.currentTimeMillis()

그러나 좀 더 복잡한 일의 경우 다음과 같이 통계적 시간 측정을 사용하고 싶을 것입니다 (조금 아래로 스크롤하여 표준 편차 등을 포함하여 표현 된 시간 측정을보십시오).

http://perf4j.codehaus.org/devguide.html


자동 생성기 코드를 가리키는 +1. 나는 항상 비슷한 문장을 사용하며 코드 템플릿 삽입에 대해 몰랐다. 이클립스로 그것을하는 방법을 알아 냈고 확실히 도움이 될 것입니다!
— Jason

모든 Codehaus 서비스가 종료되었습니다. 이제 링크가 끊어졌습니다.
— naXa

2

AOP / AspectJ 및 jcabi-aspects의@Loggable 주석을 사용 하면 쉽고 간단하게 수행 할 수 있습니다.

@Loggable(Loggable.DEBUG)
public String getSomeResult() {
  // return some value
}

이 메서드에 대한 모든 호출은 DEBUG로깅 수준이있는 SLF4J 로깅 기능으로 전송됩니다 . 그리고 모든 로그 메시지에는 실행 시간이 포함됩니다.


2

다음은 Java에서 실행 시간을 찾는 몇 가지 방법입니다.

1) System.nanoTime ()

long startTime = System.nanoTime();
.....your code....
long endTime   = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in nanoseconds  : " + totalTime);
System.out.println("Execution time in milliseconds : " + totalTime / 1000000);

2) System.currentTimeMillis ()

long startTime = System.currentTimeMillis();
.....your code....
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds  : " + totalTime);

3) Instant.now ()

long startTime = Instant.now().toEpochMilli();
.....your code....
long endTime = Instant.now().toEpochMilli();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

또는

Instant start = Instant.now();
.....your code....
Instant end = Instant.now();
Duration interval = Duration.between(start, end);
System.out.println("Execution time in seconds: " +interval.getSeconds());

4) Date.getTime ()

long startTime = new Date().getTime();
.....your code....
long endTime = new Date().getTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

1

startTime=System.currentTimeMillis()루프 상단에서 시작 시간을 길게 사용

long endTime= System.currentTimeMillis();루프의 끝 외부에 두십시오 . 밀리 초 단위의 런타임을 얻으려면 값을 빼야합니다.

나노초 단위의 시간을 원한다면 System.nanoTime()


1

측정하려는 코드를 람다로 사용하는 고차 함수를 만들었습니다.

class Utils {

    public static <T> T timeIt(String msg, Supplier<T> s) {
        long startTime = System.nanoTime();
        T t = s.get();
        long endTime = System.nanoTime();
        System.out.println(msg + ": " + (endTime - startTime) + " ns");
        return t;
    }

    public static void timeIt(String msg, Runnable r) {
       timeIt(msg, () -> {r.run(); return null; });
    }
}

다음과 같이 부르십시오.

Utils.timeIt("code 0", () ->
        System.out.println("Hallo")
);

// in case you need the result of the lambda
int i = Utils.timeIt("code 1", () ->
        5 * 5
);

산출:

코드 0 : 180528 ns
코드 1 : 12003 ns

중복을 줄이는 데 도움을 준 Andy Turner 에게 특별히 감사드립니다 . 를 참조하십시오 여기 .



0

Perf4J를 사용해 볼 수도 있습니다. 원하는 것을 수행하는 깔끔한 방법이며 설정된 시간 범위 동안 평균, 최소, 최대, 표준 편차 및 초당 트랜잭션과 같은 집계 된 성능 통계에 도움이됩니다. http://perf4j.codehaus.org/devguide.html 에서 발췌 :

StopWatch stopWatch = new LoggingStopWatch();

try {
    // the code block being timed - this is just a dummy example
    long sleepTime = (long)(Math.random() * 1000L);
    Thread.sleep(sleepTime);
    if (sleepTime > 500L) {
        throw new Exception("Throwing exception");
    }

    stopWatch.stop("codeBlock2.success", "Sleep time was < 500 ms");
} catch (Exception e) {
    stopWatch.stop("codeBlock2.failure", "Exception was: " + e);
}

산출:

INFO: start[1230493236109] time[447] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493236719] time[567] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493237286] time[986] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493238273] time[194] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238467] time[463] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238930] time[310] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239241] time[610] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493239852] time[84] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239937] time[30] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239968] time[852] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]

0
public class someClass
{
   public static void main(String[] args) // your app start point
   {
       long start = java.util.Calendar.getInstance().getTimeInMillis();

       ... your stuff ...

       long end = java.util.Calendar.getInstance().getTimeInMillis();
       System.out.println("it took this long to complete this stuff: " + (end - start) + "ms");
   }
}

0

System.currentTimeMillis ()를 사용하는 것이 적절한 방법입니다. 그러나 명령 줄을 사용하고 전체 프로그램의 시간을 대략적으로 빠르게 측정하려면 다음을 고려하십시오.

time java App

코드와 앱 시간을 수정할 수 없습니다.


이것은 코드를 실행하는 방법에 따라 다릅니다. 서버를 실행하는 코드라면 잘못된 시작 시간을 포함하게됩니다.
— Arun Ramakrishnan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.