images/logo.png
SHWB na blogspot  | Uživatel: Nepřihlášen

O programování 04 - Java Microbenchmark Harness

Ve druhém díle jsem si prakticky ověřil, že používat pro (mikro) benchmark rozdíl času začátku a konce měřené operace není to pravé ořechové, výsledné časy se při opakování testu lišily o desítky procent a výjimkou nebyly ani násobné časy. Je celkem logické, že pokud je čas měřené operace v řádech milisekund, tak je přesnost měření v milisekundách nedostatečná.

Proto jsem hledal lepší řešení a jako první jsem našel Java Microbenchmark Harness, v uvedeném odkazu je i pěkně vysvětleno, co a proč je tak obtížné na Java mikro benchmarku. Bohužel jsem ani s použitím tutoriálů zdezde dlouho nemohl testování rozchodit a ani stackoverflow moc nepomohl. Až po delším úsilí (=pár desítek minut) jsem pochopil, jak to má fungovat a implementoval jsem funkční verzi. Z výsledků jsem nejdříve nebyl moc moudrý, JMH totiž spouští celou řadu testů a měří různé charakteristiky (AverageTime, SampleTime, SingleShotTime, Throughput), ale kombinací intuice a dokumentace se dá celkem dobře pochopit, co který test znamená.

Principiálně je JMH o pár anotacích a následující příkladové konfiguraci:



final Options opt = new OptionsBuilder() .include(ListPlusPlus.class.getSimpleName()) .warmupIterations(5) .measurementIterations(5) .forks(1) .build();

Primárně jsem porovnával běžný cyklus foreach se stream().foreach(), stejně jako v mnou implementovaném benchmarku a výsledek je následující:

Benchmark Mode Cnt Score Error Units
ListPlusPlus.foreach thrpt 5 8,070 ± 2,046 ops/ms
ListPlusPlus.streamForEach thrpt 5 8,309 ± 1,935 ops/ms
ListPlusPlus.foreach avgt 5 0,125 ± 0,050 ms/op
ListPlusPlus.streamForEach avgt 5 0,124 ± 0,028 ms/op
ListPlusPlus.foreach sample 40681 0,123 ± 0,001 ms/op
ListPlusPlus.streamForEach sample 39544 0,127 ± 0,003 ms/op
ListPlusPlus.foreach ss 5 1,059 ± 2,028 ms/op
ListPlusPlus.streamForEach ss 5 0,422 ± 0,677 ms/op

I tento test potvrdil, že stream().foreach() je výkonnější s výjimkou prvního spuštění. Stabilita měření však není ani v případě JMH zdaleka ideální, výsledek 1 ± 2 ms představuje docela velký výkyv a defakto se až tak neliší od naivní implementace založené na rozdílu času. Další nevýhodou JMH je to, že spuštění testu je opravdu pomalé - 5 warmapů a 5 iterací na měření mi v naivní implementaci trvalo pár vteřin ale v JMH to zabralo přes dvě minuty.

Spustil jsem ještě testy pro porovnání prvních pěti volání a opět nic nového pod sluncem, pouze potvrzení již konstatovaného závěru.

 # Benchmark mode: Single shot invocation time
 # Benchmark: k8.chapter4.support.ListPlusPlus.streamForEach

# Run progress: 99,98% complete, ETA 00:00:00 # Fork: 1 of 1 # Warmup Iteration 1: 75,062 ms/op # Warmup Iteration 2: 0,926 ms/op # Warmup Iteration 3: 0,593 ms/op # Warmup Iteration 4: 0,717 ms/op # Warmup Iteration 5: 0,792 ms/op Iteration 1: 0,745 ms/op
# Benchmark mode: Single shot invocation time # Benchmark: k8.chapter4.support.ListPlusPlus.foreach
# Run progress: 99,97% complete, ETA 00:00:00 # Fork: 1 of 1 # Warmup Iteration 1: 3,075 ms/op # Warmup Iteration 2: 2,849 ms/op # Warmup Iteration 3: 1,956 ms/op # Warmup Iteration 4: 2,559 ms/op # Warmup Iteration 5: 2,547 ms/op Iteration 1: 2,181 ms/op

Řekl bych, že JMH nemá oproti naivní implementaci založené na rozdílu času velký přínos v časové stabilitě testů.

Mohl bych si sice vypomoci trochou statistiky (průměrná odchylka atd), ale problematika mikro benchmarků mě v tuto chvíli nepřipadá dostatečně zajímavá. Pokud by mě však zajímala, tak bych hledal buď jiný framework nebo bych zobecnil svůj naivní přístup a např. místo Date() bych zkusil použít přesnější Instant(). Nebo bych pro měření mohl použít aspekty, protože jak naivní implementace tak JMH znamenají zásahy do kódu, což se mi nelíbí, protože musím udržovat "dvě" varianty kódu, jednu testovací a druhou produkční.

28.12.2016
Přidat názor:
Vyhrazuji si právo libovolný komentář smazat bez udání důvodu. Kritika mi nevadí, ale chci omezit anonymní výkřiky, které nemají s tématem nic společného.
V textu je možné používat HTML tagy a tuto zjednodušenou MarkDown syntaxi
Jméno
Text
Postřehy:
31.07.2019: Arduino 01 - Motivace k elektrotechnice
To jsem se jednou, nechci říct nudil, ale zkrátka jsem narazil na knihy "Porty, bajty, osmibity" a "Hradla, volty, jednočipy" od Martina Malého z produkce sdružení NIC.CZ, které jsou volně dostupné na knihy.nic.cz.
extravaganza.controverso@seznam.cz: Zdravím, krásný a informacemi nabitý blog. Musím pochválit. Plánuji rozjet undergroundový zin, co by se týkal black matalu, ambientu, satanismu, left hand
Poslední diskuse Postřehy
O programování 06 - Návrhové vzory - síla i slabina Javy
P.S. samozrejme "Context" mel byt "Client" .. To jsem jen narazil na nejak divne pojmenovany diagram.. (Context je samozrejme trosku neco jineho...)
...
David | 25.02.2017
O programování 06 - Návrhové vzory - síla i slabina Javy
To k cemu jsi dosel (tedy implementace LooperRunner + ILoopMethod), tak je ta prava Strategy by GoF :) To co je tam dulezite je ze Context (LooperRunner) je oddeleny od Strategy (ILoopMethod),
...
David | 25.02.2017
O programování 03 - Přehlednost funkcionálního zápisu v Java 8
Máš pravdu, to map je tam zbytečné. Odněkud jsem to opsal a nezkontroloval. Tím ovšem trochu padá pointa celého článku.
...
Saha | 14.12.2016
O programování 03 - Přehlednost funkcionálního zápisu v Java 8
Jen takova otazka k tomu druhemu prikladu:
Proc tam tu cast s "map" ktera de facto s prvky toho streamu nic nedela? Nestacilo by
list.stream().reduce(0, Integer::sum);
?
Ja teda moc
...
David P. | 13.12.2016
Paleo na půl - 01 - První tři dny bez mléka
Kvalitní hořké čokolády jsou bez mléka.. :) (a to i ty méně "kvalitní"). Mléko bývá součástí jen těch "sladkých".
...
David | 04.05.2015
Statistiky
Aktualizováno: 29.09.2019
Počet článků/fotek: 1374/13846
(C) Saha - 1990 - 2019 - Verze 1.3.32 - 11.05.2019 - Generated by SHREC 2.216
Veškeré zde uvedené materiály vyjadřují pouze moje soukromé názory (s výjimkou knihy návštěv a diskusí, kam může přispívat kdokoliv), a pokud s nimi někdo nesouhlasí, tak je to jeho problém, nikoliv můj.