2014-10-25 2 views
0

나는 다음과 같은 간단한 코드 몇 가지 성능 테스트 (백만 정수 주위 요약)를하고 있었다 :자바 실행 시간은 문자열 포맷팅의 영향을 받습니까?

final int[] array = new int[1024 * 1024]; 

// populate values 
for (int i = 0; i < array.length; i++) { 
    array[i] = i % 100; 
} 

long start, end, sum = 0; 

start = System.nanoTime(); 

// calculate sum 
for (int i : array) { 
    sum += i; 
} 

end = System.nanoTime() - start; 

System.out.println(end); 

평균 실행 시간은 약 1.8ms했다.

그런 다음 테스트 결과 프레젠테이션을 변경하기로 결정했습니다. 나는 다음과 같은 성명 (형식 문자열)와 System.out.println(end) 대체 :

System.out.printf("Time in %dns, sum: %d\n", end, sum); 

을 그리고 내 평균 실행 시간은 약 2.8ms 것을 발견 할 때 매우 놀라운 일이었다. 그것은 단지 1 밀리 세컨드 (큰 문제는 아니지만)이지만 다른 한편으로 그것은 약 약 50 %입니다. 더 많은 것은 테스트 결과 프레젠테이션 (및 형식화)이 종료 시간 측정 후에 수행되므로 이론적으로 은 평균 실행 시간에 영향을주지 않아야합니다.

System.out.printf 진술을 추가 한 후 평균 실행 시간이 더 오래 걸리는 이유를 알고 계십니까? 재정렬 (변수 : end에 값을 할당하기 전에 서식이 지정됨)으로 인해 발생 했습니까?

+2

이러한 측정 값을 신뢰할 수있게 재현 할 수 있습니까? 밀리 세컨드 차이는 아무리 큰 a * relative * 차이가 있더라도 무작위 노이즈의 범위에 있습니다. – delnan

+3

충분한 테스트를 수행하지 않았습니다. 100.000 시간을하고 두 방법이 모두 측정하는 방법을보십시오. 내 컴퓨터에서 몇 가지 간단한 테스트를 통해 모두 동일한 범위에 있음을 알 수 있습니다. –

답변

5

나는 이것으로 결론을 도출 할 수 없다고 생각합니다. 기본적으로, 벤치 마크는 결함이있다 : 그것은 측정을 캡처하기 전에 그것은 JVM을 에 필요한 조치를 취을 따뜻하게하지 않습니다

  1. .

  2. 측정중인 "작업"을 수행하는 루프를 최적화 할 수 있습니다. 컴파일러 (javac 또는 JIT 컴파일러)는 sum이 사용되지 않는다고 추론 할 수 있으므로 계산하지 않습니다.

이러한 결함 중 하나가 표시되는 결과를 왜곡시킬 수 있습니다.


벤치 마크가 제대로 작성 되었다면 멋진 형식이 측정 된 시간에 전혀 기여하지 않아야합니다.

+0

귀하의 답변 Stephane에 많은 감사드립니다. 문제가 2 번과 관련이있는 것으로 보입니다. 'sum' ('System.out.println (sum) ')으로 print 문을 추가 할 때 두 결과 모두 2.8ms와 같은 수준이되었습니다. 좋은 캐치. – Tom

+8

예, Dead Code Elimination이 현재 작동 중입니다. JIT 컴파일러에 의해'javac'가 아니라, 확실히. 제대로 벤치마킹 한 경우'sum'을 사용하거나 사용하지 않을 경우의 차이가 훨씬 커졌습니다. 교훈 : 최대한주의를 기울여 측정하고 'jmh'와 같은 적절한 측정 장치를 사용하십시오. –

관련 문제