å»å¹ŽããããªèšäºãåºãŠããŠãå人çã«ã¯ãã£ããèå³ãåŒããŸããã
Javaã®ãã€ã¯ããã³ãããŒã¯ããŒã«ãJMHã
http://acro-engineer.hatenablog.com/entry/2013/11/07/120606
以åãJavaã®ãã£ãã·ã¥ã®ãã³ãããŒã¯ãåãã®ã«Google Caliperã®0.5ã䜿ã£ãŠéãã ããšãããã®ã§ããã1.0ã«ãªã£ãŠã©ããå€ãªåãã«ãªã£ãŠããŠè«ŠããŠãããšããã«åºãŠããèšäºã ã£ãã®ã§ã倧å€åèã«ãªããŸããã
ã§ãè©Šããè©Šãããšæã£ãŠãããã¡ã«ãæ°ä»ãã°å¹Žãå€ãã£ãŠããŸããããŒã
ãŸãä»ããã§ãããã£ãŠã¿ãŸãããã
Code Tools: jmh
http://openjdk.java.net/projects/code-tools/jmh/
æºå
å èšäºã«ã¯JMHèªäœããã«ãããæ¹æ³ãã玹ä»ãããŠããŸãããä»ã¯Maven Centralã«0.2ãŸã§ã¢ãããããŠããã®ã§ããã¡ãã䜿çšããããšã«ããŸãã
MavenäŸåé¢ä¿ã¯ã以äžã®ããã«å®çŸ©ããŸãã
<dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>0.2</version> </dependency>
ãŸãããã«ãããŠJARãçæããã®ã§ããããã®æJMHèªäœãJARã«å«ããå¿ èŠããããããbuildïŒpluginsé äžã«ä»¥äžã®èšå®ãå ããŸãã
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.2</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <finalName>microbenchmarks</finalName> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>org.openjdk.jmh.Main</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin>
ããšã¯ããã€ã¯ããã³ãããŒã¯ãè¡ãããã®ã³ãŒããçšæããŸãã
ãã®èšå®ã§ããœãŒã¹ã³ãŒããæžããåŸã«ä»¥äžã®ã³ãã³ããå®è¡ãããš
$ mvn package
targetãã£ã¬ã¯ããªé äžã«ãmicrobenchmarks.jarããçæãããã®ã§ããã¡ãã䜿çšããŸãã
å®è¡ã³ãã³ãã¯ããããªæãã§ãã
$ java -jar target/microbenchmarks.jar [ãªãã·ã§ã³]
ã§ã¯ãããã€ããµã³ãã«ã玹ä»ãããšå ±ã«ãå®è¡äŸãèŒããŠãããŸãããã
ãªããJMHèªäœã®ãµã³ãã«ã³ãŒãã¯ããã¡ãã§ç¢ºèªããããšãã§ããŸãã
ãããã¯ããªããžããªèªäœãMercurialã§ãã§ãã¯ã¢ãŠãããŸãããã
$ hg clone http://hg.openjdk.java.net/code-tools/jmh/ jmh
HelloWorldçãª
ã§ã¯ããŸãã¯åçŽãªåŠçãæžããŠã¿ãŸãã
src/main/java/org/littlewings/jmh/example/HelloJmh.java
package org.littlewings.jmh.example; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.GenerateMicroBenchmark; public class HelloJmh { @GenerateMicroBenchmark public void simpleBench() throws InterruptedException { TimeUnit.MILLISECONDS.sleep(500); } }
ãã³ãããŒã¯å¯Ÿè±¡ã®ã¡ãœããã«ã¯ã@GenerateMicroBenchmarkã¢ãããŒã·ã§ã³ãä»äžããŸããã²ãšã€ã®ã¯ã©ã¹ã«ãè€æ°ã®@GenerateMicroBenchmarkã¢ãããŒã·ã§ã³ãä»äžããã¡ãœãããèšããŠå€§äžå€«ã§ãã
ä»åã¯ã1åã®åŒã³åºãã§500msecã¹ãªãŒãããåŠçãçšæããŸããã
ããã§ã¯ããã«ãããŠå®è¡ããŠã¿ãŸãã
$ java -jar target/microbenchmarks.jar -wi 3 -i 3 -f 1 -r 1s -bm thrpt -tu s
å®è¡éäžã«ã¯ãã®ãããªé²æç¶æ ã衚瀺ããã
# Fork: 1 of 1 # Warmup: 3 iterations, 1 s each # Measurement: 3 iterations, 1 s each # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Running: org.littlewings.jmh.example.HelloJmh.simpleBench # Warmup Iteration 1: 2.000 ops/s # Warmup Iteration 2: 2.000 ops/s # Warmup Iteration 3: 2.000 ops/s Iteration 1: 2.000 ops/s Iteration 2: 2.000 ops/s Iteration 3: 2.000 ops/s Result : 2.000 ±(99.9%) 0.000 ops/s Statistics: (min, avg, max) = (2.000, 2.000, 2.000), stdev = 0.000 Confidence interval (99.9%): [2.000, 2.000]
æçµçã«ããããªçµæã衚瀺ãããŸãã
Benchmark Mode Thr Count Sec Mean Mean error Units o.l.j.e.HelloJmh.simpleBench thrpt 1 3 1 2.000 0.000 ops/s
ä»åã¯è¡šç€ºãç§åäœã«ããŠããã®ã§ã1ç§ã§2åã®åŒã³åºãâŠãŸããããã§ããã
èµ·åæã«ãããããªãã·ã§ã³ãæå®ããŠããŸãããå®éã«ã¯æå®ããªããŠãããã©ã«ãã§ããããåããŠãããŸããæå®ãããªãã·ã§ã³ã®æå³ã解説ããŠãããš
ãªãã·ã§ã³ | æå³ | æå®å¯èœãªå€ |
---|---|---|
-wi | ãŠã©ãŒã ã¢ããæã®ç¹°ãè¿ãåæ°ïŒèšæž¬ã«ã¯å«ãŸããªãïŒ | intã§æå®ã§ããæ°åïŒäŸïŒ3ïŒ |
-i | èšæž¬ãè¡ãåæ° | intã§æå®ã§ããæ°åïŒäŸïŒ3ïŒ |
-f | ãã©ãŒã¯ã®æ°ãããã§ã¯ããã³ãããŒã¯ã®ã»ããïŒãŠã©ãŒã ã¢ããããèšæž¬ãŸã§ïŒã®ç¹°ãè¿ãåæ°ãšæããã°OK | intã§æå®ã§ããæ°åïŒäŸïŒ1ïŒ |
-r | èšæž¬ãè¡ãéã®ãå®è¡æé | 100sã 200msãªã© |
-bm | ãã³ãããŒã¯ã®ã¢ãŒã | thrptïŒã¹ã«ãŒãããïŒãavgtïŒå¹³åïŒãsampleïŒTime distribution, percentile estimationïŒãssïŒã·ã³ã°ã«ã·ã§ããïŒãallïŒå·Šã«äžããã¢ãŒããå šéšå®è¡ããïŒ |
-tu | çµæ衚瀺ã®éã®ãæéã®åäœ | mã sã msã usã ns |
æå®å¯èœãªãªãã·ã§ã³ã®äžèŠ§ã¯ã以äžã®ã³ãã³ãã§èŠãããšãã§ããŸãã
$ java -jar target/microbenchmarks.jar -h
ããã©ã«ãå€ã«ã€ããŠã¯ã以äžãèŠããšããã§ãããã
æšæºåå·®ïŒ
http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-core/src/main/java/org/openjdk/jmh/runner/parameters/Defaults.java
ç¹°ãè¿ãå®è¡
ãã³ãããŒã¯ã§ã®æž¬å®å¯Ÿè±¡ãè€æ°åŒã³åºãéã«ãäœåºŠã®åŒã³åºãã1åã®èšæž¬ãšæããããJMHã«æå®ããããšãã§ããŸãã
以äžãã³ãŒãäŸã
src/main/java/org/littlewings/jmh/example/Loop.java
package org.littlewings.jmh.example; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.GenerateMicroBenchmark; import org.openjdk.jmh.annotations.OperationsPerInvocation; public class Loop { public void method(int limit) throws InterruptedException { for (int i = 0; i < limit; i++) { TimeUnit.MILLISECONDS.sleep(10); } } @GenerateMicroBenchmark @OperationsPerInvocation(1) public void invoke1() throws InterruptedException { method(1); } @GenerateMicroBenchmark @OperationsPerInvocation(100) public void invoke100() throws InterruptedException { method(100); } }
æ¬åœã«èšæž¬ãããã®ã¯methodã¡ãœããã ãšããå Žåãèšæž¬çšã®ã¡ãœãããšããŠinvoke1ãšinvoke100ã®2ã€ã®ã¡ãœãããçšæããŸããinvoke1ã¯1åã®åŒã³åºãã§æ¬åœã«èšæž¬ãããã¡ãœãããã¡ãœããã1ååŒãã ããšã«ãinvoke100ã¯1åã®åŒã³åºãã§æ¬åœã«èšæž¬ãããã¡ãœããã100ååŒãã§ããããšããJMHã«æããŠããããšã«ãªã£ãŠããŸãã
methodå ã§ã¯ãæå®ã®ã«ãŒãããšã«10msecã¹ãªãŒãããŸãããªã®ã§ãinvoke100ã¡ãœãããåŒã³åºããš1ç§å°ã ã¹ãªãŒãããããšã«ãªããŸããã
ããã¯ããã³ãããŒã¯ã¢ãŒããallã«ããŠçµæãèŠãŠã¿ãŸãããã
$ java -jar target/microbenchmarks.jar -wi 3 -i 3 -f 1 -r 1s -bm all -tu s
ãããªæãã«ãªããŸãã
Benchmark Mode Thr Count Sec Mean Mean error Units o.l.j.e.Loop.invoke1 thrpt 1 3 1 87.800 40.489 ops/s o.l.j.e.Loop.invoke100 thrpt 1 3 1 90.289 10.820 ops/s o.l.j.e.Loop.invoke1 avgt 1 3 1 0.011 0.001 s/op o.l.j.e.Loop.invoke100 avgt 1 3 1 0.011 0.000 s/op o.l.j.e.Loop.invoke1 sample 1 258 1 0.012 0.000 s/op o.l.j.e.Loop.invoke100 sample 1 3 1 1.191 0.054 s/op o.l.j.e.Loop.invoke1 ss 1 3 0 0.014 0.041 s o.l.j.e.Loop.invoke100 ss 1 3 0 1.107 0.130 s
ã¹ã«ãŒãããã¯ã100ååŒã³åºãã®æ¹ããè¥å¹²é ãããããå¹³åã¯åãã§ããããªã®ã§ãJMHåŽã§@GenerateMicroBenchmarkãä»äžããã¡ãœããèªèº«ããèšæž¬å¯Ÿè±¡ã100ååŒãã ããšãèªèããŠããŸãã代ããã«ãã·ã³ã°ã«ã·ã§ããïŒssïŒã¯ãã¹ãªãŒãã®çµæããã€ã¬ã¯ãã«çŸããŠããã®ããããããããšæããŸãã
ãã³ãããŒã¯ã«ç¶æ ãæããã
ãã³ãããŒã¯ã®ã¯ã©ã¹ã«ãã£ãŒã«ããªã©ã®ç¶æ ãæãããŠããã®åæåïŒçµäºãªã©ãã³ã³ãããŒã«ã§ããŸãã
ã§ã¯ããµã³ãã«ãã
src/main/java/org/littlewings/jmh/example/TestState.java
package org.littlewings.jmh.example; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.GenerateMicroBenchmark; import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; @State(Scope.Thread) public class TestState { private long counter = 0; @Setup //@Setup(Level.Iteration) public void setup() { System.out.println("========== setup =========="); counter = 0; } @GenerateMicroBenchmark public void methodA() { counter++; } @GenerateMicroBenchmark public void methodB() { counter++; } @TearDown //@TearDown(Level.Iteration) public void tearDown() { System.out.println("========== teardown =========="); System.out.println("counter = " + counter); } }
æåã«ã
@State(Scope.Thread) public class TestState {
ãšå®£èšããŠãããšããããã€ã³ãã§ããããã§ãã¹ã¬ããåäœã«ãã³ãããŒã¯ãæã€ããã«ããŸãã
ãã®ä»ãå¿ é ã§ã¯ãããŸããã@Setupã¢ãããŒã·ã§ã³ã@TearDownã¢ãããŒã·ã§ã³ãä»äžããã¡ãœãããäœæããããšã§ãåæåïŒçµäºåŠçãæžãããšãã§ããŸãã
@Setup //@Setup(Level.Iteration) public void setup() { System.out.println("========== setup =========="); counter = 0; } @TearDown //@TearDown(Level.Iteration) public void tearDown() { System.out.println("========== teardown =========="); System.out.println("counter = " + counter); }
JMHã®ãµã³ãã«ã§ã¯ã@TearDownã¢ãããŒã·ã§ã³ãä»äžããã¡ãœããã§ã¢ãµãŒã·ã§ã³ãè¡ã£ãŠããŸããã
@Setupã¢ãããŒã·ã§ã³ã@TearDownã¢ãããŒã·ã§ã³ã§ã³ã¡ã³ãã¢ãŠãã§LevelãæžããŠããŸãããããã«ã¯3ã€ã®ãã¿ãŒã³ãæå®ã§ããŸããããããã
- Trial ⊠ãã³ãããŒã¯ã®åäœïŒãŠã©ãŒã ã¢ããããèšæž¬çµäºãŸã§ïŒ
- Iteration ⊠ãã³ãããŒã¯ã®ã€ãã¬ãŒã·ã§ã³ã®åäœ
- Invocation ⊠èšæž¬å¯Ÿè±¡ã®åŒã³åºãåäœ
ãæå®ã§ããŸããããéåžžãTrialãIterationãæå®ãããã ãšæããŸããInvocationã¯ãJavadocã§ãã®ãã£ããèŠåãããŠããŸãâŠã
ã§ãä»åã®äŸã¯@Setupãš@TearDownã§System.outããŠããã ããªã®ã§ãå®è¡ãããš
$ java -jar target/microbenchmarks.jar -wi 3 -i 3 -f 1 -r 1s -bm thrpt -tu s
ã¡ãã£ãšã¬ããŒãã®çµæã«å²ã蟌ãŸããŠããŸããããããªè¡šç€ºã«ãªããŸãã
# Fork: 1 of 1 ========== setup ========== # Warmup: 3 iterations, 1 s each # Measurement: 3 iterations, 1 s each # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Running: org.littlewings.jmh.example.TestState.methodB # Warmup Iteration 1: 393825934.400 ops/s # Warmup Iteration 2: 384291389.050 ops/s # Warmup Iteration 3: 402733190.600 ops/s Iteration 1: 393833628.933 ops/s Iteration 2: 403786121.067 ops/s Iteration 3: ========== teardown ========== counter = 2387745388 404992957.983 ops/s # Fork: 1 of 1 ========== setup ========== # Warmup: 3 iterations, 1 s each # Measurement: 3 iterations, 1 s each # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Running: org.littlewings.jmh.example.TestState.methodA # Warmup Iteration 1: 384264742.033 ops/s # Warmup Iteration 2: 380980549.233 ops/s # Warmup Iteration 3: 354685731.983 ops/s Iteration 1: 355758333.350 ops/s Iteration 2: 383169984.083 ops/s Iteration 3: ========== teardown ========== counter = 2205967045 345683238.517 ops/s Result : 361537185.317 ±(99.9%) 250075812.730 ops/s Statistics: (min, avg, max) = (345683238.517, 361537185.317, 383169984.083), stdev = 19400009.558 Confidence interval (99.9%): [111461372.587, 611612998.047]
ã€ãŸããããã©ã«ãã¯Trialã§ãããŠã©ãŒã ã¢ããã®åã«@Setupã¢ãããŒã·ã§ã³ãä»äžããã¡ãœãããåŒã³åºãããå šéšãçµãããš@TearDownãä»äžããã¡ãœãããåŒã³åºãããŸãã
ãŸããåãã¯ã©ã¹ã®@GenerateMicroBenchmarkã¢ãããŒã·ã§ã³ãä»äžããã¡ãœããåäœã«ããã³ãããŒã¯ã¯å®è¡ãããã®ã§ãã®åäœã§åŒã³åºãããŸãã
ã§ã¯ãããã§Iterationã«å€ããŠ
@Setup(Level.Iteration) @TearDown(Level.Iteration)
å®è¡ã
# Fork: 1 of 1 ========== setup ==========# Warmup: 3 iterations, 1 s each # Measurement: 3 iterations, 1 s each # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Running: org.littlewings.jmh.example.TestState.methodA # Warmup Iteration 1: ========== teardown ========== counter = 393415410 ========== setup ========== 393832584.250 ops/s # Warmup Iteration 2: ========== teardown ========== counter = 393429045 389109403.767 ops/s========== setup ========== # Warmup Iteration 3: ========== teardown ========== counter = 388305539 387911634.900 ops/s Iteration 1: ========== setup ========== ========== teardown ========== counter = 396708771 396541675.083 ops/s Iteration 2: ========== setup ========== ========== teardown ========== counter = 396693148 396416333.250 ops/s ========== setup ========== Iteration 3: ========== teardown ========== counter = 387101506 387070113.833 ops/s Result : 393342707.389 ±(99.9%) 70028758.090 ops/s Statistics: (min, avg, max) = (387070113.833, 393342707.389, 396541675.083), stdev = 5432586.868 Confidence interval (99.9%): [323313949.299, 463371465.479] # Fork: 1 of 1 ========== setup ========== # Warmup: 3 iterations, 1 s each # Measurement: 3 iterations, 1 s each # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Running: org.littlewings.jmh.example.TestState.methodB # Warmup Iteration 1: ========== teardown ========== counter = 382855076 381309718.083 ops/s # Warmup Iteration 2: ========== setup ========== ========== teardown ========== counter = 405691075 407024043.733 ops/s # Warmup Iteration 3: ========== setup ========== ========== teardown ========== counter = 380215869 379928576.517 ops/s Iteration 1: ========== setup ========== ========== teardown ========== counter = 365053007 364777073.200 ops/s Iteration 2: ========== setup ========== ========== teardown ========== counter = 408294746 407903593.383 ops/s ========== setup ==========Iteration 3: ========== teardown ========== counter = 412189352 411940886.967 ops/s Result : 394873851.183 ±(99.9%) 336991524.691 ops/s Statistics: (min, avg, max) = (364777073.200, 394873851.183, 411940886.967), stdev = 26142627.423 Confidence interval (99.9%): [57882326.493, 731865375.874]
ãŠã©ãŒã ã¢ãããšãåã€ãã¬ãŒã·ã§ã³æ¯ã«@SetupïŒ@TearDownãåŒã³åºãããããã«ãªããŸãã
ãŸãããã®ãããã§ããã°ããããªâŠã
ãªããã³ãã³ãã©ã€ã³ã®ãªãã·ã§ã³ã§æå®ãããã©ã¡ãŒã¿ãªã©ã¯ãã¢ãããŒã·ã§ã³ã§ãã³ãããŒã¯å¯Ÿè±¡ã®ã¡ãœãããã¯ã©ã¹ã«æå®ããããšãã§ããŸãã詳ããã¯ã以äžã«å®çŸ©ãããŠããã¢ãããŒã·ã§ã³ãåæå
ãããŠãµã³ãã«ã³ãŒãã§äœ¿ãæ¹ãèŠãŠã¿ãŸãããã
ããã§ãJMHãšGatlingã䜿ããããã«ãªã£ãâŠãšãããªãã