BenchMark工具-JMH介绍

fpcm 10年前

    JMH是有OpenJDK开发的基准测试(Benchmark)工具。JMH可以为写基准测试和运行测试提供很好的支持。JMH在Concurrent Benchmarks也提供很好的支持,可以说是多功能测试工具。JMH在2013被公布出来,现在最新版本到1.9。

    JMH基本用法:

       JMH环境构建

      1 使用maven工程,直接在项目中引入相应的jar包

    

<dependency>      <groupId>org.openjdk.jmh</groupId>      <artifactId>jmh-core</artifactId>      <version>${jmh.version}</version>  </dependency>  <dependency>      <groupId>org.openjdk.jmh</groupId>      <artifactId>jmh-generator-annprocess</artifactId>      <version>${jmh.version}</version>      <scope>provided</scope>  </dependency>


   2 或者直接用JMH的archetype创建:

           mvn archetype:generate \            -DinteractiveMode=false \            -DarchetypeGroupId=org.openjdk.jmh \            -DarchetypeArtifactId=jmh-java-benchmark-archetype \            -DgroupId=com.yao \            -DartifactId=jmh-demo \            -Dversion=1.0


  环境搭建好之后然后就可以写相应的测试用例了

  Demo如下

public class JMHSample_01_HelloWorld {      @Benchmark      public void wellHelloThere() {          // this method was intentionally left blank.      }      /*           * a) Via command-line:       *    $ mvn clean install       *    $ java -jar target/benchmarks.jar JMHSample_01       *       * JMH generates self-contained JARs, bundling JMH together with it.       * The runtime options for the JMH are available with "-h":       *    $ java -jar target/benchmarks.jar -h       *       * b) Via the Java API:       *    (see the JMH homepage for possible caveats when running from IDE:       *      http://openjdk.java.net/projects/code-tools/jmh/)       */        public static void main(String[] args) throws RunnerException {          Options opt = new OptionsBuilder()                  .include(JMHSample_01_HelloWorld.class.getSimpleName())                  .forks(1)                  .build();          new Runner(opt).run();      }


运行上面的Demo有两种方法:一个是直接打包,然后会在target中生成benchmarks.jar,里面带有main方法,就直接可以运行:java -jar target/benchmarks.jar。运行后的结果如下格式:(运行的结果也写入指定的文件)

Result "wellHelloThere":      3142305096.924 ±(99.9%) 17949665.603 ops/s [Average]      (min, avg, max) = (2907217981.526, 3142305096.924, 3226536099.659), stdev = 76000008.112        CI (99.9%): [3124355431.320, 3160254762.527] (assumes normal distribution)      # Run complete. Total time: 00:06:42    Benchmark                Mode  Cnt           Score          Error  Units    MyBenchmark.testMethod  thrpt  200  3142305096.924 ± 17949665.603  ops/s


同时也支持在IDE中直接运行。

往往在写用例的时候,可以不写main方法,直接在方法上写个Junit的Test注解 ,功能和main相同。

比如netty5中为所有的benchmarks写了一个基类如下:

@Warmup(iterations = AbstractMicrobenchmark.DEFAULT_WARMUP_ITERATIONS)  @Measurement(iterations = AbstractMicrobenchmark.DEFAULT_MEASURE_ITERATIONS)  @Fork(AbstractMicrobenchmark.DEFAULT_FORKS)  @State(Scope.Thread)  public class AbstractMicrobenchmark {        protected static final int DEFAULT_WARMUP_ITERATIONS = 10;      protected static final int DEFAULT_MEASURE_ITERATIONS = 10;      protected static final int DEFAULT_FORKS = 2;        public static final class HarnessExecutor extends ThreadPoolExecutor {          public HarnessExecutor(int maxThreads, String prefix) {              super(0, maxThreads, 1L, TimeUnit.DAYS, new SynchronousQueue<Runnable>(),                    new DefaultThreadFactory(prefix));              System.out.println("Using harness executor");          }      }        protected static final String[] JVM_ARGS = {          "-server", "-dsa", "-da", "-ea:io.netty...", "-Xms768m", "-Xmx768m",          "-XX:MaxDirectMemorySize=768m", "-XX:+AggressiveOpts", "-XX:+UseBiasedLocking",          "-XX:+UseFastAccessorMethods", "-XX:+UseStringCache", "-XX:+OptimizeStringConcat",          "-XX:+HeapDumpOnOutOfMemoryError", "-Dio.netty.noResourceLeakDetection",          "-Dharness.executor=CUSTOM",          "-Dharness.executor.class=io.netty.microbench.util.AbstractMicrobenchmark$HarnessExecutor"      };        static {          ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);      }        @Test      public void run() throws Exception {          String className = getClass().getSimpleName();            ChainedOptionsBuilder runnerOptions = new OptionsBuilder()              .include(".*" + className + ".*")              .jvmArgs(JVM_ARGS);            if (getWarmupIterations() > 0) {              runnerOptions.warmupIterations(getWarmupIterations());          }            if (getMeasureIterations() > 0) {              runnerOptions.measurementIterations(getMeasureIterations());          }            if (getForks() > 0) {              runnerOptions.forks(getForks());          }            if (getReportDir() != null) {              String filePath = getReportDir() + className + ".json";              File file = new File(filePath);              if (file.exists()) {                  file.delete();              } else {                  file.getParentFile().mkdirs();                  file.createNewFile();              }                runnerOptions.resultFormat(ResultFormatType.JSON);              runnerOptions.result(filePath);          }            new Runner(runnerOptions.build()).run();      }        protected int getWarmupIterations() {          return SystemPropertyUtil.getInt("warmupIterations", -1);      }        protected int getMeasureIterations() {          return SystemPropertyUtil.getInt("measureIterations", -1);      }        protected int getForks() {          return SystemPropertyUtil.getInt("forks", -1);      }        protected String getReportDir() {          return SystemPropertyUtil.get("perfReportDir");      }  }


    

    我这里仅仅是入门性的介绍,具体的参数和用法本人也不是很熟悉。

具体介绍和用法参照:http://openjdk.java.net/projects/code-tools/jmh/

本人通过官网摘抄的例子,传到github上了:https://github.com/WangErXiao/jmh-demo

END-----------------------------------------------------------------------------------------

转发标注来源:http://my.oschina.net/robinyao/blog/408285