Java에서 올바른 마이크로 벤치 마크를 작성하려면 어떻게해야합니까?
Java에서 올바른 마이크로 벤치 마크를 어떻게 작성 (및 실행)합니까?
생각해야 할 다양한 사항을 설명하는 몇 가지 코드 샘플과 주석을 찾고 있습니다.
예 : 벤치 마크는 시간 / 반복 또는 반복 / 시간을 측정해야하며 그 이유는 무엇입니까?
관련 : 스톱워치 벤치마킹이 허용됩니까?
Java HotSpot 제작자의 마이크로 벤치 마크 작성에 대한 팁 :
규칙 0 : JVM 및 마이크로 벤치마킹에 대한 평판 좋은 논문을 읽으십시오. 좋은 사람은 Brian Goetz, 2005 입니다. 마이크로 벤치 마크에서 너무 많은 것을 기대하지 마십시오. 제한된 범위의 JVM 성능 특성 만 측정합니다.
규칙 1 : 타이밍 단계 전에 모든 초기화 및 컴파일을 트리거하기에 충분한 테스트 커널을 실행하는 준비 단계를 항상 포함합니다. (워밍업 단계에서는 반복 횟수를 줄여도 좋습니다. 경험상 수만 번의 내부 루프 반복을 사용하는 것이 좋습니다.)
규칙 2 : 항상 실행 -XX:+PrintCompilation
, -verbose:gc
당신은 컴파일러와 JVM의 다른 부분은 타이밍 단계에서 예상치 못한 일을하지 않는 것을 확인할 수 있도록, 등.
규칙 2.1 : 타이밍 및 준비 단계의 시작과 끝에서 메시지를 인쇄하여 타이밍 단계 중에 규칙 2의 출력이 없는지 확인할 수 있습니다.
규칙 3 :-client
및 -server
, OSR 및 일반 편집 의 차이점을 인식하십시오 . -XX:+PrintCompilation
플래그는 예를 들어, 비 초기 진입 점을 표시하기에 - 기호 OSR 컴파일을보고합니다 Trouble$1::run @ 2 (41 bytes)
. 최상의 성능을 원한다면 서버보다 클라이언트를 선호하고 OSR을 정기적으로 선호하십시오.
규칙 4 : 초기화 효과에 유의하십시오. 인쇄는 클래스를로드하고 초기화하므로 타이밍 단계에서 처음으로 인쇄하지 마십시오. 특별히 클래스로드를 테스트하지 않는 한 (그리고이 경우 테스트 클래스 만로드) 준비 단계 (또는 최종보고 단계) 외부에서 새 클래스를로드하지 마십시오. 규칙 2는 이러한 영향에 대한 첫 번째 방어선입니다.
규칙 5 : 최적화 해제 및 재 컴파일 효과에 유의하십시오. 타이밍 단계에서 처음으로 코드 경로를 사용하지 마십시오. 컴파일러가 경로가 전혀 사용되지 않을 것이라는 이전의 낙관적 가정을 기반으로 코드를 정크 및 재 컴파일 할 수 있기 때문입니다. 규칙 2는 이러한 영향에 대한 첫 번째 방어선입니다.
규칙 6 : 적절한 도구를 사용하여 컴파일러의 마음을 읽고 그것이 생성하는 코드에 놀라게 될 것입니다. 무언가를 더 빠르게 또는 더 느리게 만드는 것에 대한 이론을 형성하기 전에 코드를 직접 검사하십시오.
규칙 7 : 측정에서 노이즈를 줄이십시오. 조용한 컴퓨터에서 벤치 마크를 실행하고이를 여러 번 실행하여 이상 값을 제거합니다. -Xbatch
응용 프로그램과 함께 컴파일러를 직렬화하는 데 사용 하고 컴파일러 -XX:CICompilerCount=1
가 자체적으로 병렬로 실행되지 않도록 설정 을 고려 합니다. 최선을 다해 GC 오버 헤드를 줄이고 Xmx
(충분히 크게) 동일하게 설정 Xms
하고 가능한 UseEpsilonGC
경우 사용하십시오.
규칙 8 : 벤치 마크에 라이브러리를 사용하십시오. 아마도 더 효율적이고이 유일한 목적을 위해 이미 디버깅 되었기 때문입니다. 같은 JMH , 캘리퍼스 또는 빌과 자바에 대한 바울의 우수한 UCSD 벤치 마크 .
이 질문이 답변 된 것으로 표시되었지만 마이크로 벤치 마크를 작성하는 데 도움이되는 두 개의 라이브러리를 언급하고 싶습니다.
시작하기 튜토리얼
시작하기 튜토리얼
- JVM에서 벤치마킹 함정 방지
- http://nitschinger.at/Using-JMH-for-Java-Microbenchmarking
- http://java-performance.info/jmh/
Java 벤치 마크의 중요한 사항은 다음과 같습니다.
- 코드를 여러 번 실행하여 먼저 JIT를 예열 시간이 초과되기까지의 시간 을
- 결과를 몇 초 또는 (더 나은) 수십 초 내에 측정 할 수있을만큼 충분히 오래 실행해야합니다.
System.gc()
반복간에 호출 할 수는 없지만 테스트간에 실행하여 각 테스트가 작업 할 "깨끗한"메모리 공간을 확보 할 수 있도록하는 것이 좋습니다. (예,gc()
보증 이라기보다는 힌트에 가깝지만 제 경험으로는 실제로 가비지 수집이 될 가능성 이 높습니다 .)- 나는 반복과 시간을 표시하는 것을 좋아하며, "최고"알고리즘이 1.0의 점수를 얻고 다른 알고리즘은 상대적인 방식으로 점수를 매길 수 있도록 시간 / 반복 점수를 조정할 수 있습니다. 즉 , 반복 횟수와 시간을 변경하면서 오랜 시간 동안 모든 알고리즘을 실행할 수 있지만 여전히 비슷한 결과를 얻을 수 있습니다.
.NET에서 벤치마킹 프레임 워크의 설계에 대해 블로그를 작성하는 중입니다. 내가있어 부부 의 이전 게시물 몇 가지 아이디어를 제공 할 수 있습니다 - 모든 것이 물론 적절한 것, 그러나 그것의 일부가 될 수있다.
jmh 는 최근 OpenJDK에 추가되었으며 Oracle의 일부 성능 엔지니어가 작성했습니다. 확실히 볼 가치가 있습니다.
jmh는 Java 및 JVM을 대상으로하는 기타 언어로 작성된 나노 / 마이크로 / 매크로 벤치 마크를 빌드, 실행 및 분석하기위한 Java 하네스입니다.
샘플 테스트 주석에 묻혀있는 매우 흥미로운 정보 입니다.
또한보십시오:
벤치 마크는 시간 / 반복 또는 반복 / 시간을 측정해야하며 그 이유는 무엇입니까?
이에 따라 무엇을 당신이 시험에 노력하고 있습니다.
지연 시간 에 관심이있는 경우 시간 / 반복을 사용 하고 처리량에 관심이있는 경우 반복 / 시간을 사용합니다.
벤치 마크 코드에서 계산 된 결과를 어떻게 든 사용하는지 확인하십시오. 그렇지 않으면 코드를 최적화 할 수 있습니다.
두 알고리즘을 비교하려는 경우 순서를 번갈아 가며 각각에 대해 최소 두 개의 벤치 마크를 수행하십시오. 즉 :
for(i=1..n)
alg1();
for(i=1..n)
alg2();
for(i=1..n)
alg2();
for(i=1..n)
alg1();
다른 패스에서 동일한 알고리즘의 런타임에서 몇 가지 눈에 띄는 차이점 (때로는 5-10 %)을 발견했습니다.
Also, make sure that n is very large, so that the runtime of each loop is at the very least 10 seconds or so. The more iterations, the more significant figures in your benchmark time and the more reliable that data is.
There are many possible pitfalls for writing micro-benchmarks in Java.
First: You have to calculate with all sorts of events that take time more or less random: Garbage collection, caching effects (of OS for files and of CPU for memory), IO etc.
Second: You cannot trust the accuracy of the measured times for very short intervals.
Third: The JVM optimizes your code while executing. So different runs in the same JVM-instance will become faster and faster.
My recommendations: Make your benchmark run some seconds, that is more reliable than a runtime over milliseconds. Warm up the JVM (means running the benchmark at least once without measuring, that the JVM can run optimizations). And run your benchmark multiple times (maybe 5 times) and take the median-value. Run every micro-benchmark in a new JVM-instance (call for every benchmark new Java) otherwise optimization effects of the JVM can influence later running tests. Don't execute things, that aren't executed in the warmup-phase (as this could trigger class-load and recompilation).
It should also be noted that it might also be important to analyze the results of the micro benchmark when comparing different implementations. Therefore a significance test should be made.
This is because implementation A
might be faster during most of the runs of the benchmark than implementation B
. But A
might also have a higher spread, so the measured performance benefit of A
won't be of any significance when compared with B
.
So it is also important to write and run a micro benchmark correctly, but also to analyze it correctly.
http://opt.sourceforge.net/ Java Micro Benchmark - control tasks required to determine the comparative performance characteristics of the computer system on different platforms. Can be used to guide optimization decisions and to compare different Java implementations.
To add to the other excellent advice, I'd also be mindful of the following:
For some CPUs (e.g. Intel Core i5 range with TurboBoost), the temperature (and number of cores currently being used, as well as thier utilisation percent) affects the clock speed. Since CPUs are dynamically clocked, this can affect your results. For example, if you have a single-threaded application, the maximum clock speed (with TurboBoost) is higher than for an application using all cores. This can therefore interfere with comparisons of single and multi-threaded performance on some systems. Bear in mind that the temperature and volatages also affect how long Turbo frequency is maintained.
Perhaps a more fundamentally important aspect that you have direct control over: make sure you're measuring the right thing! For example, if you're using System.nanoTime()
to benchmark a particular bit of code, put the calls to the assignment in places that make sense to avoid measuring things which you aren't interested in. For example, don't do:
long startTime = System.nanoTime();
//code here...
System.out.println("Code took "+(System.nanoTime()-startTime)+"nano seconds");
Problem is you're not immediately getting the end time when the code has finished. Instead, try the following:
final long endTime, startTime = System.nanoTime();
//code here...
endTime = System.nanoTime();
System.out.println("Code took "+(endTime-startTime)+"nano seconds");
참고URL : https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java
'Nice programing' 카테고리의 다른 글
줄거리에서 범례를 제거하는 방법 (0) | 2020.09.28 |
---|---|
알고리즘의 시간 복잡성을 찾는 방법 (0) | 2020.09.28 |
iOS 버전은 어떻게 확인하나요? (0) | 2020.09.28 |
단위 테스트 C 코드 (0) | 2020.09.28 |
OS X에서 환경 변수 설정 (0) | 2020.09.28 |