Jak napisać poprawny mikro-benchmark w Javie?

Jak napisać (i uruchomić) poprawny mikro-benchmark w Javie?

Szukam tutaj próbek kodu i komentarzy ilustrujących różne rzeczy do przemyślenia.

Przykład: czy benchmark powinien mierzyć czas/iterację lub iteracje / czas i dlaczego?

Related: czy stoper benchmarking jest akceptowalny?

Author: Community, 2009-02-02

11 answers

Wskazówki dotyczące pisania mikro benchmarków od twórców Java HotSpot :

Reguła 0: przeczytaj renomowaną pracę na temat JVMs i mikro-benchmarkingu. Dobry jest Brian Goetz, 2005. Nie oczekuj zbyt wiele od mikro-benchmarków; mierzą one jedynie ograniczony zakres charakterystyki wydajności JVM.

Reguła 1: zawsze dołączaj fazę rozgrzewki, która uruchamia jądro testowe przez całą drogę, wystarczającą do uruchomienia wszystkich inicjalizacji i Kompilacje przed fazą (fazami) czasową. (Mniej iteracji jest OK w fazie rozgrzewki. Zasadą jest kilkadziesiąt tysięcy iteracji pętli wewnętrznej.)

Reguła 2: zawsze biegaj z -XX:+PrintCompilation, -verbose:gc, itd., dzięki czemu możesz sprawdzić, czy kompilator i inne części JVM nie wykonują nieoczekiwanej pracy podczas fazy czasowej.

Reguła 2.1: wypisuje komunikaty na początku i końcu faz czasu i rozgrzewki, dzięki czemu możesz sprawdzić, czy nie ma wyjścia z reguły 2 w fazie czasowej.

Reguła 3: Bądź świadomy różnicy między-klientem i-serwerem, a OSR i regularnymi kompilacjami. Znacznik -XX:+PrintCompilation zgłasza Kompilacje OSR ze znakiem at oznaczającym początkowy punkt wejścia, na przykład: Trouble$1::run @ 2 (41 bytes). Preferuj Serwer od klienta i regularny od OSR, jeśli chcesz uzyskać najlepszą wydajność.

Zasada 4: Bądź świadomy efektów inicjalizacji. Nie Drukuj po raz pierwszy w fazie pomiaru czasu, ponieważ drukowanie ładuje się i inicjalizuje klasy. Nie ładuj nowych klas poza fazą rozgrzewki (lub końcową fazą raportowania), chyba że testujesz Ładowanie klas specjalnie (i w takim przypadku ładuj tylko klasy testowe). Zasada 2 to twoja pierwsza linia obrony przed takimi skutkami.

Reguła 5: Bądź świadomy efektów deoptymizacji i rekompilacji. Nie należy pobierać żadnej ścieżki kodu po raz pierwszy w fazie czasowej, ponieważ kompilator może zarekomendować i przekompilować kod, bazując na wcześniejszym optymizmie założenie, że ścieżka w ogóle nie będzie używana. Zasada 2 to twoja pierwsza linia obrony przed takimi skutkami.

Reguła 6: użyj odpowiednich narzędzi, aby odczytać umysł kompilatora i spodziewaj się zaskoczenia kodem, który tworzy. Sprawdź sam kod, zanim zaczniesz tworzyć teorie na temat tego, co sprawia, że coś jest szybsze lub wolniejsze.

Reguła 7: zmniejsz hałas podczas pomiarów. Uruchom swój benchmark na cichej maszynie i uruchom go kilka razy, odrzucając odstające. Użyj -Xbatch do serializacji kompilatora z aplikacją i rozważ ustawienie -XX:CICompilerCount=1, aby zapobiec równoległemu uruchomieniu kompilatora. Postaraj się jak najlepiej zmniejszyć obciążenie GC, Ustaw Xmx (wystarczająco duży) równa się Xms i użyj UseEpsilonGC jeśli jest dostępny.

Reguła 8: użyj biblioteki dla swojego benchmarka, ponieważ jest ona prawdopodobnie bardziej wydajna i została już debugowana tylko w tym celu. Takie jak JMH, Caliper lub Bill and Paul ' s Doskonałe Benchmarki UCSD dla Javy .

 670
Author: 11 revs, 11 users 62%Eugene Kuleshov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-09 09:47:17

Wiem, że to pytanie zostało oznaczone jako odpowiedź, ale chciałem wspomnieć o dwóch bibliotekach, które umożliwiają pisanie mikro benchmarków

Caliper od Google

Pierwsze kroki tutoriale

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

JMH z OpenJDK

Pierwsze kroki tutoriale

  1. unikanie pułapek benchmarkingu na JVM
  2. http://nitschinger.at/Using-JMH-for-Java-Microbenchmarking
  3. http://java-performance.info/jmh/
 215
Author: Aravind R. Yarram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 15:10:03

Ważne rzeczy dla benchmarków Javy to:

  • rozgrzej najpierw JIT, uruchamiając kod kilka razy, zanim go zmierzysz
  • upewnij się, że działa wystarczająco długo, aby móc zmierzyć wyniki w sekundach lub (lepiej) dziesiątkach sekund
  • chociaż nie można wywoływać System.gc() między iteracjami, dobrym pomysłem jest uruchamianie go między testami, aby każdy test miał nadzieję uzyskać "czystą" przestrzeń pamięci do pracy. (Tak, {[1] } jest bardziej podpowiedzią niż gwarancją, ale jest bardzo prawdopodobnie to naprawdę zbierze śmieci z mojego doświadczenia.)
  • lubię wyświetlać iteracje i czas oraz wynik czasu/iteracji, który można skalować tak, aby "najlepszy" algorytm otrzymał wynik 1.0, a inne są oceniane w sposób względny. Oznacza to, że możesz uruchomić wszystkie algorytmy przez długi czas, zmieniając zarówno liczbę iteracji, jak i czas, ale wciąż uzyskując porównywalne wyniki.
Jestem właśnie w trakcie blogowania o projekcie benchmarking framework w .NET. mam parę z wcześniejszych postów, które mogą dać ci kilka pomysłów - nie wszystko będzie oczywiście odpowiednie, ale niektóre z nich mogą być.
 73
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-20 08:02:53

Jmh jest ostatnim dodatkiem do OpenJDK i został napisany przez niektórych inżynierów wydajności z Oracle. Na pewno warto zajrzeć.

JMH to uprząż Java do budowania, uruchamiania i analizowania Nano/mikro/makro benchmarków napisanych w Javie i innych językach ukierunkowanych na JVM.

Bardzo ciekawe informacje Zakopane w przykładowe testy Komentarze .

Zobacz też:

 40
Author: assylias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-21 07:47:26

Czy benchmark powinien mierzyć czas/iterację lub iteracje / czas i dlaczego?

To zależy od tego, co próbujesz przetestować. Jeśli jesteś zainteresowany opóźnieniami, użyj time / iteracji, a jeśli jesteś zainteresowany iteracją/czasem przepustowości, użyj iteracji / czasu.
 17
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-02 19:54:35

Upewnij się, że w jakiś sposób używasz wyników, które są obliczane w kodzie porównawczym. W przeciwnym razie Twój kod może zostać zoptymalizowany.

 14
Author: Peter Štibraný,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-02 18:00:10

Jeśli próbujesz porównać dwa algorytmy, wykonaj co najmniej dwa benchmarki na każdym z nich, zmieniając kolejność. tj.:

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

Znalazłem pewne zauważalne różnice (czasami 5-10%) w czasie wykonywania tego samego algorytmu w różnych przebiegach..

Upewnij się również, że n jest bardzo duża, tak aby czas działania każdej pętli wynosił co najmniej 10 sekund. Im więcej iteracji, tym bardziej znaczące liczby w czasie benchmarku i tym bardziej wiarygodne dane jest.

 12
Author: Kip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-02 17:57:01

Istnieje wiele możliwych pułapek pisania mikro-benchmarków w Javie.

Po pierwsze: musisz obliczyć z różnego rodzaju zdarzeń, które zajmują mniej lub bardziej przypadkowe: Garbage collection, efekty buforowania (OS dla plików i CPU dla pamięci), IO itp.

Po drugie: nie można ufać dokładności mierzonych czasów w bardzo krótkich odstępach czasu.

Po Trzecie: JVM optymalizuje Twój kod podczas wykonywania. Więc różne biegi w tej samej instancji JVM staną się szybsze i szybciej.

Moje zalecenia: spraw, aby twój benchmark działał kilka sekund, co jest bardziej niezawodne niż runtime w ciągu milisekund. Rozgrzej JVM (oznacza uruchomienie benchmarka co najmniej raz bez pomiaru, aby JVM mógł uruchomić optymalizacje). I uruchomić swój benchmark wiele razy (może 5 razy) i wziąć wartość mediana. Uruchom każdy mikro-benchmark w nowej instancji JVM (call for every benchmark new Java) w przeciwnym razie efekty optymalizacji JVM mogą wpłynąć na późniejsze uruchomione testy. Nie. wykonuje rzeczy, które nie są wykonywane w fazie warmup (ponieważ może to spowodować obciążenie klas i rekompilację).

 12
Author: Mnementh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-23 11:32:55

Należy również zauważyć, że ważne może być również przeanalizowanie wyników mikro benchmark podczas porównywania różnych implementacji. Dlatego należy wykonać test istotności.

Wynika to z faktu, że implementacja A może być szybsza podczas większości uruchomień benchmarka niż implementacja B. Ale A może również mieć wyższy spread, więc zmierzona korzyść z wydajności A nie będzie miała żadnego znaczenia w porównaniu z B.

Więc to ważne jest również, aby poprawnie napisać i uruchomić mikro benchmark, ale także poprawnie go przeanalizować.

 7
Author: SpaceTrucker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-21 14:04:05

Http://opt.sourceforge.net / Java Micro Benchmark-zadania kontrolne wymagane do określenia porównawczej charakterystyki wydajności systemu komputerowego na różnych platformach. Może być używany do kierowania decyzjami optymalizacyjnymi i porównywania różnych implementacji Javy.

 6
Author: Yuriy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-18 23:22:11

Aby dodać do innych doskonałych rad, chciałbym również pamiętać o następujących:

W przypadku niektórych procesorów (np. Intel Core i5 z TurboBoost) temperatura (i liczba obecnie używanych rdzeni, a także procent wykorzystania) wpływa na Prędkość zegara. Ponieważ procesory są dynamicznie taktowane, może to wpłynąć na wyniki. Na przykład, jeśli masz aplikację jednowątkową, maksymalna prędkość zegara (w przypadku TurboBoost) jest wyższa niż w przypadku aplikacji wykorzystującej wszystkie rdzenie. To może w związku z tym koliduje z porównaniami wydajności jedno-i wielowątkowej w niektórych systemach. Należy pamiętać, że temperatura i lotność wpływają również na to, jak długo utrzymywana jest częstotliwość Turbo.

Być może bardziej istotny aspekt, nad którym masz bezpośrednią kontrolę: upewnij się, że mierzysz właściwą rzecz! Na przykład, jeśli używasz System.nanoTime() do porównywania określonego fragmentu kodu, umieść wywołania do przypisania w miejscach, które mają sens, aby uniknąć pomiaru rzeczy, które nie jestem zainteresowany. Na przykład nie rób:

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

Problem polega na tym, że nie otrzymujesz od razu czasu zakończenia kodu. Zamiast tego spróbuj:

final long endTime, startTime = System.nanoTime();
//code here...
endTime = System.nanoTime();
System.out.println("Code took "+(endTime-startTime)+"nano seconds");
 5
Author: Sina Madani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-19 19:21:23