문제

Java에서 올바른 마이크로 벤치 마크를 어떻게 쓰고 실행합니까?

나는 몇 가지 코드 샘플과 댓글을 찾고 있습니다.

예 : 벤치 마크는 시간/반복 또는 반복/시간을 측정해야하며 그 이유는 무엇입니까?

관련된: 스톱워치 벤치마킹이 허용됩니까?

도움이 되었습니까?

해결책

마이크로 벤치 마크 작성에 대한 팁 Java Hotspot의 제작자로부터:

규칙 0 : JVMS 및 Micro-Benchmarking에 대한 평판이 좋은 논문을 읽으십시오. 좋은 것은입니다 Brian Goetz, 2005. 마이크로 벤치 마크에서 너무 많이 기대하지 마십시오. 제한된 범위의 JVM 성능 특성 만 측정합니다.

Rule 1: 타이밍 단계 전에 모든 초기화 및 컴파일을 트리거하기에 충분한 테스트 커널을 실행하는 워밍업 단계가 항상 포함되어 있습니다. (워밍업 단계에서는 반복이 적습니다. 경험의 규칙은 수만 개의 내부 루프 반복입니다.)

Rule 2: 항상 실행하십시오 -XX:+PrintCompilation, -verbose:gc, 등. 따라서 JVM의 컴파일러 및 기타 부분이 타이밍 단계에서 예기치 않은 작업을 수행하지 않는지 확인할 수 있습니다.

규칙 2.1 : 타이밍 및 워밍업 단계의 시작과 끝에서 메시지를 인쇄하므로 타이밍 단계에서 규칙 2의 출력이 없음을 확인할 수 있습니다.

규칙 3 : 차이점을 알고 있어야합니다 -client 그리고 -server, 및 OSR 및 정기적 인 편집. 그만큼 -XX:+PrintCompilation 플래그는 예를 들어 비 초기 입력 점을 나타내는 At-Sign을 사용하여 OSR 컴파일을보고합니다. Trouble$1::run @ 2 (41 bytes). 최상의 성능을 누른 경우 서버를 클라이언트보다 선호하고 OSR에 정기적으로 선호하십시오.

Rule 4: 초기화 효과를 알고 있어야합니다. 인쇄로드 및 수업을 초기화하기 때문에 타이밍 단계에서 처음으로 인쇄하지 마십시오. 클래스 로딩을 구체적으로 테스트하지 않는 한 (이 경우 테스트 클래스 만로드)를 테스트하지 않는 한 워밍업 단계 (또는 최종보고 단계) 외부에서 새로운 클래스를로드하지 마십시오. 규칙 2는 그러한 효과에 대한 첫 번째 방어선입니다.

Rule 5: 최적화 및 재 컴파일 효과를 알고 있어야합니다. 컴파일러가 경로가 전혀 사용되지 않았다는 초기 낙관적 가정에 따라 컴파일러가 쓰레기를 쓰러 뜨리고 다시 컴파일 할 수 있기 때문에 타이밍 단계에서 처음으로 코드 경로를 가져 가지 마십시오. 규칙 2는 그러한 효과에 대한 첫 번째 방어선입니다.

규칙 6 : 적절한 도구를 사용하여 컴파일러의 마음을 읽고 생성하는 코드에 놀라게 될 것으로 예상됩니다. 더 빠르거나 느리게 무언가를 만드는 것에 대한 이론을 형성하기 전에 코드를 직접 검사하십시오.

Rule 7: 측정의 노이즈를 줄입니다. 조용한 기계에서 벤치 마크를 실행하고 여러 번 실행하여 이상치를 버립니다. 사용 -Xbatch 응용 프로그램으로 컴파일러를 직렬화하고 설정을 고려하십시오. -XX:CICompilerCount=1 컴파일러가 자신과 병렬로 실행되는 것을 방지합니다. GC 오버 헤드를 줄이려면 최선을 다하십시오 Xmx(충분히) Xms 그리고 사용 UseEpsilonGC 사용 가능한 경우.

규칙 8 : 벤치 마크에 라이브러리를 사용하여 더 효율적이며 이미이 단독 목적을 위해 디버깅되었으므로 이미 라이브러리를 사용하십시오. 와 같은 JMH, 캘리퍼스 또는 Java를위한 Bill and Paul의 훌륭한 UCSD 벤치 마크.

다른 팁

이 질문이 답변으로 표시되어 있다는 것을 알고 있지만 마이크로 벤치 마크를 작성하는 데 도움이되는 두 개의 라이브러리를 언급하고 싶었습니다.

구글의 캘리퍼

시작 튜토리얼

  1. http://codingjunkie.net/micro-benchmarking-with-caliper/
  2. http://vertexlabs.co.uk/blog/caliper

OpenJDK에서 JMH

시작 튜토리얼

  1. JVM의 벤치마킹 함정을 피합니다
  2. http://nitschinger.at/using-jmh-for-java-microbenchmarking
  3. http://java-performance.info/jmh/

Java 벤치 마크의 중요한 사항은 다음과 같습니다.

  • 코드를 여러 번 실행하여 JIT를 먼저 예열하십시오. 타이밍 전 그것
  • 결과를 몇 초 또는 (더 나은) 수십 초 안에 측정 할 수있을 정도로 오랫동안 실행하십시오.
  • 당신은 전화 할 수 없지만 System.gc() 반복 사이에 테스트간에 실행하는 것이 좋습니다. 따라서 각 테스트는 "깨끗한"메모리 공간을 얻을 수 있습니다. (예, gc() 보증보다 힌트이지만 매우 ~할 것 같은 실제로 내 경험에 쓰레기가 수집 될 것입니다.)
  • 나는 반복과 시간을 표시하고, "최고의"알고리즘이 1.0 점을 얻고 다른 것들이 상대적인 방식으로 점수를 매기도록 스케일링 할 수있는 시간/반복을 표시하는 것을 좋아합니다. 이것은 당신이 실행할 수 있음을 의미합니다 모두 오랜 시간 동안의 알고리즘으로 반복과 시간의 수가 다양하지만 여전히 비슷한 결과를 얻습니다.

저는 .NET의 벤치마킹 프레임 워크 설계에 대해 블로깅하는 과정에 있습니다. 나는 가지고있다 커플이전 게시물 어떤 아이디어를 줄 수 있습니다. 물론 모든 것이 적절하지는 않지만 일부는 그럴 수 있습니다.

JMH 최근 OpenJDK에 추가되었으며 Oracle의 일부 성능 엔지니어가 작성했습니다. 확실히 볼만한 가치가 있습니다.

JMH는 Java 및 JVM을 목표로 작성된 Java 및 기타 언어로 작성된 Nano/Micro/Macro 벤치 마크를 구축, 실행 및 분석하기위한 Java 하네스입니다.

매우 흥미로운 정보가 묻혀 있습니다 샘플을 테스트합니다.

또한보십시오:

벤치 마크는 시간/반복 또는 반복/시간을 측정해야하며 왜 그런가?

그것은 의존합니다 무엇 당신은 테스트를 시도하고 있습니다.

관심이 있다면 지연 시간, 시간/반복을 사용하고 관심이있는 경우 처리량, 반복/시간을 사용하십시오.

어떻게 든 벤치마킹 코드로 계산 된 결과를 사용해야합니다. 그렇지 않으면 코드를 최적화 할 수 있습니다.

두 개의 알고리즘을 비교하려는 경우 순서를 번갈아 가면서 각각에 대해 최소한 두 개의 벤치 마크를 수행하십시오. 즉:

for(i=1..n)
  alg1();
for(i=1..n)
  alg2();
for(i=1..n)
  alg2();
for(i=1..n)
  alg1();

다른 패스에서 동일한 알고리즘의 런타임에서 눈에 띄는 차이 (가끔 5-10%)를 발견했습니다.

또한 확인하십시오 N 각 루프의 런타임이 최소 10 초 정도이되도록 매우 크기 때문에. 반복이 많을수록 벤치 마크 시간의 중요한 수치가 높고 데이터가 더 신뢰할 수 있습니다.

Java에서 마이크로 벤치 마크를 작성하는 데 많은 가능한 함정이 있습니다.

첫째 : 무작위로 시간이 걸리는 모든 종류의 이벤트로 계산해야합니다 : 쓰레기 수집, 캐싱 효과 (파일의 OS 및 메모리의 CPU), IO 등.

둘째 : 매우 짧은 간격으로 측정 된 시간의 정확도를 신뢰할 수 없습니다.

셋째 : JVM은 실행 중에 코드를 최적화합니다. 따라서 동일한 JVM 인스턴스에서 다른 실행이 더 빠르고 빠르게됩니다.

내 권장 사항 : 벤치 마크를 몇 초 동안 실행하게하십시오. 그것은 밀리 초 이상의 런타임보다 더 안정적입니다. JVM을 예열합니다 (JVM이 최적화를 실행할 수 있음을 측정하지 않고 적어도 한 번 벤치 마크를 실행한다는 의미). 벤치 마크를 여러 번 (5 번) 실행하고 중간 값을 가져갑니다. 모든 마이크로 벤치 마크를 새로운 JVM 인스턴스 (모든 벤치 마크 새로운 Java에 대해 호출)로 실행하십시오. 그렇지 않으면 JVM의 최적화 효과는 나중에 실행되는 테스트에 영향을 줄 수 있습니다. 워밍업 단계에서 실행되지 않는 물건을 실행하지 마십시오 (클래스로드 및 재 컴파일을 유발할 수 있으므로).

또한 다른 구현을 비교할 때 마이크로 벤치 마크의 결과를 분석하는 것이 중요 할 수도 있습니다. 따라서 a 중요 테스트 만들어야합니다.

구현 때문입니다 A 구현보다 대부분의 벤치 마크 실행 중에 더 빠를 수 있습니다. B. 하지만 A 스프레드가 더 높을 수 있으므로 측정 된 성능 이점 A 비교할 때는 중요하지 않습니다 B.

따라서 마이크로 벤치 마크를 올바르게 작성하고 실행하는 것이 중요하며 올바르게 분석하는 것이 중요합니다.

http://opt.sourceforge.net/ Java Micro Benchmark- 다른 플랫폼에서 컴퓨터 시스템의 비교 성능 특성을 결정하는 데 필요한 제어 작업. 최적화 결정을 안내하고 다른 Java 구현을 비교하는 데 사용할 수 있습니다.

다른 훌륭한 조언에 추가하기 위해 다음을 염두에 두어야합니다.

일부 CPU (예 : Turboboost가있는 Intel Core i5 범위)의 경우, 온도 (및 현재 사용중인 코어 수 및 이용률 백분율)는 클럭 속도에 영향을 미칩니다. CPU가 동적으로 클럭이므로 결과에 영향을 줄 수 있습니다. 예를 들어, 단일 스레드 애플리케이션이있는 경우 최대 클럭 속도 (TurboBoost 포함)는 모든 코어를 사용하는 응용 프로그램보다 높습니다. 따라서 일부 시스템에서 단일 및 멀티 스레드 성능의 비교를 방해 할 수 있습니다. 온도와 휘발은 또한 터보 주파수가 얼마나 오래 유지되는지에도 영향을 미친다는 것을 명심하십시오.

아마도 당신이 직접 통제 할 수있는 더 근본적으로 중요한 측면 일 것입니다 : 올바른 것을 측정하고 있는지 확인하십시오! 예를 들어, 사용하는 경우 System.nanoTime() 특정 코드를 벤치마킹하려면 관심이없는 물건을 측정하지 않기 위해 의미가있는 장소에서 과제에 대한 통화를 배치합니다. 예를 들어,하지 마십시오.

long startTime = System.nanoTime();
//code here...
System.out.println("Code took "+(System.nanoTime()-startTime)+"nano seconds");

문제는 코드가 완료되었을 때 즉시 종료 시간을 얻지 못한다는 것입니다. 대신 다음을 시도하십시오.

final long endTime, startTime = System.nanoTime();
//code here...
endTime = System.nanoTime();
System.out.println("Code took "+(endTime-startTime)+"nano seconds");
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top