Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałFranciszek Makowski Został zmieniony 7 lat temu
1
Testowanie Wydajności Kodu za pomocą Narzędzia JMH
Wojciech Oczkowski
2
O czym będziemy mówić Czym są benchmarki i w czym mogą nam pomóc Jakie są problemy z mierzeniem wydajności kodu Javy Jak JMH pozwala uniknąć typowych błędów Praktyczne przykłady
3
Wojciech Oczkowski >> 20 lat programowania dla przyjemności
>> 10 lat zawodowego programowania w Javie Branże: Obronna, telco / call-center, finansowa Szkolenia Wydajność, Architektura, Integracja Właściciel IT Kontekst Lider Bydgoszcz JUG Aktywny członek Toruń JUG Ojciec, mąż, żeglarz
4
Benchmarki Porównywanie wydajności alternatywnych rozwiązań
Sprawdzanie wydajności bez konieczności budowy całego rozwiązania Eksperymentowanie z nowymi rozwiązaniami Tuning Benchmarki - testy rozwiązań skupione na mierzeniu i porównywaniu ich wydajności.
5
Co w tym trudnego? long start = System.currentTimeMillis(); work(); System.out.println( System.currentTimeMillis() - start); Nawet najlepsi się na tym wykładali Choć trzeba przyznać że czasy wtedy były inne. (wersja javy, wydajność sprzętu)
6
what could possibly go wrong? Pomiar CZASU
Ziarnistość pomiaru czasu (~30 ns Linux, ~300 ns Windows [1t]) Ukryty narzut System.nanoTime(); Błąd pomiaru różnice w implementacji timerów w systemach operacyjnych - Najczęściej badanie wydajności opieramy o pomiar czasu Dokładność pomiaru czasu jest jednak ograniczona Chcąc podejść do sprawy profesjonalnie nie możemy skupić się na pojedynczym pomiarze Trzeba określić granice niepewności, odchylenie standardowe itp., jest do tego cała teoria opisana np. w monografii GUM.
7
what could possibly go wrong? Optymalizacje kompilatora - pętle
Rozwijanie pętli Piplineing long start = System.nanoTime(); for (int i = 0; i < ; i++) { work(); } System.out.println((System.nanoTime() - start)/100000);
8
what could possibly go wrong
what could possibly go wrong? Optymalizacje kompilatora – Dead Code ELIMINATION public void measuredMethod(){ // start measurement int result = work(); // end of measurement }
9
what could possibly go wrong
what could possibly go wrong? Optymalizacje kompilatora – COnSTANT FOLDING public int measuredMethod(){ // start measurement return work(); // end of measurement }
10
what could possibly go wrong? FALSE Sharing
int someCounter; int completelyDifferentCounter; // on Thread 1 public int measuredMethod1(){ return work(someCounter); } // on Thread 2 public int measuredMethod2(){ return work(completelyDifferentCounter); }
11
what could possibly go wrong? Warm up
-XX:CompileThreshold=[1500,2000,10000] -XX:-PrintCompilation -XX:MaxInlineSize=35 -XX:+PrintInlining -XX:LoopUnrollLimit=n -zależy od charakterystyki aplikacji -czasami interesuje nas worst case bo spodziewamy się że nie będzie czasu na warmup
12
what could possibly go wrong? Różnice systemów operacyjnych
Różnice w implementacji JVM Różnice timerów Różnice scheduler’ów 32 vs 64 bit Niektóre optymalizacje dostępne są dla wybranych OS’ów Niektóre bug’i też ;)
13
Czym jest JMH i jak może pomóc
Narzędzie do budowania benchmarków Pomaga w uniknięciu typowych problemów Nie zwalnia z myślenia o nich. Java -> org.openjdk.jmh:jmh-java-benchmark-archetype Scala -> org.openjdk.jmh:jmh-scala-benchmark-archetype -> sbt-jmh plugin Groovy -> org.openjdk.jmh:jmh-groovy-benchmark-archetype Kotlin -> org.openjdk.jmh:jmh-java-benchmark-archetype
14
Nowy benchmark package pl.itkontekst.jmhtest; import org.openjdk.jmh.annotations.Benchmark; public class MyBenchmark public void testMethod(){ }
15
# JMH 1.14.1 (released 13 days ago)
# VM version: JDK 1.8.0_77, VM b03 # VM invoker: C:\Program Files\Java\jre1.8.0_77\bin\java.exe # VM options: <none> # Warmup: 20 iterations, 1 s each # Measurement: 20 iterations, 1 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Benchmark: pl.itkontekst.jmhtest.MyBenchmark.testMethod # Run progress: 0,00% complete, ETA 00:06:40 # Fork: 1 of 10 # Warmup Iteration 1: ,400 ops/s # Warmup Iteration 2: ,963 ops/s … Iteration 19: ,371 ops/s Iteration 20: ,138 ops/s Result "testMethod": ,008 ?(99.9%) ,964 ops/s [Average] (min, avg, max) = ( ,716, ,008, ,191), stdev = ,353 CI (99.9%): [ ,045, ,972] (assumes normal distribution) # Run complete. Total time: 00:06:43 Benchmark Mode Cnt Score Error Units MyBenchmark.testMethod thrpt ,008 ? ,964 ops/s
16
Opcje pomiarów = public class MyBenchmark { @Benchmark public void testMethod() { } }
17
Klasy Stanu, setup, parametry, Black Hole
@State(Scope.Benchmark) public static class MyState { @Param({"1","2","3"}) int value; @Setup public void init(){} public void testAdd(Blackhole blackhole,MyState state) { blackhole.consume(state.value+state.value); Blackhole.consumeCPU(10); public void testMethod(Blackhole blackhole) { Blackhole.consumeCPU(10); }
18
Wątki, Grupy, Padding @Threads(4) public class MyBenchmark { @State(Scope.Benchmark) public static class MyState { @Param({"2"}) int value; } @State(Scope.Benchmark) public static class MyState2 { @Param({"1"}) int value2; } @Benchmark @Group("add") public void testAdd(Blackhole blackhole,MyState state) { blackhole.consume(state.value+state.value); } @Benchmark @Group("add") public void testAdd2(Blackhole blackhole,MyState2 state) { blackhole.consume(state.value2+state.value2); } }
19
Kontrola pracy kompilatora
@CompilerControl(CompilerControl.Mode.DONT_INLINE) public void testDontInline(){} @CompilerControl(CompilerControl.Mode.INLINE) public void testForceInline(){} @CompilerControl(CompilerControl.Mode.EXCLUDE) public void testDontCompile(){}
20
Programowa kontrola uruchamiania
public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() include(MyBenchmark.class.getSimpleName()) warmupIterations(1) measurementIterations(3) forks(1) build(); new Runner(opt).run(); }
21
Profilery java -jar benchmarks.jar -lprof Supported profilers:
cl: Classloader profiling via standard MBeans comp: JIT compiler profiling via standard MBeans gc: GC profiling via standard MBeans hs_cl: HotSpot (tm) classloader profiling via implementation-specific MBeans hs_comp: HotSpot (tm) JIT compiler profiling via implementation-specific MBeans hs_gc: HotSpot (tm) memory manager (GC) profiling via implementation-specific MBeans hs_rt: HotSpot (tm) runtime profiling via implementation-specific MBeans hs_thr: HotSpot (tm) threading subsystem via implementation-specific MBeans pauses: Pauses profiler perf: Linux perf Statistics perfasm: Linux perf + PrintAssembly Profiler perfnorm: Linux perf statistics, normalized by operation count stack: Simple and naive Java stack profiler Unsupported profilers: xperfasm: <none>
22
Profilery Stack profiler:
....[Thread state distributions] 97,2% RUNNABLE 2,8% WAITING ....[Thread state: RUNNABLE] 56,8% 58,5% pl.itkontekst.jmhtest.MyBenchmark.testAdd 39,8% 41,0% pl.itkontekst.jmhtest.generated.MyBenchmark_add_jmhTest.testAdd_thrpt_jmhStub 0,3% 0,3% sun.misc.Unsafe.compareAndSwapInt 0,1% 0,1% java.lang.Thread.currentThread 0,1% 0,1% sun.misc.Unsafe.unpark ....[Thread state: WAITING] 2,8% 100,0% sun.misc.Unsafe.park
23
Wyniki java -jar benchmarks.jar -lrf
Available formats: text, csv, scsv, json, latex java -jar benchmarks.jar -rff output.csv
24
PODSUMOWANIE Pisanie Benchmarków nie jest trywialne
JMH pomaga w unikaniu typowych problemów ale nie zwalnia z myślenia o nich JMH nie zastąpi ostatecznych testów wydajnościowych JIT to potężny oręż, który może Ci obciąć rękę kiedy nie będziesz uważny
25
Warto posłuchać / poczytać
JMH Samples Aleksey Shipilëv – dzieła wybrane Jarosław Pałka – dzieła wybrane Charlie Hunt – dzieła wybrane Scott Oaks – dzieła wybrane Kirk Pepperdine – dzieła wybrane
26
Pytania?
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.