背景

许多时候需要对比不同的框架或工具或算法, 选择使用性能更优的那一个。通常的做法是

long start = System.currentTimeMillis();
for(int i=0; i<size; i++){
    doSomeWork();
}
long end = System.currentTimeMillis();
System.out.println("took time : "+(end-start));

但这样的做法非常不严谨, 因为当独立频繁运行这一小块代码时,Jvm可能会针对性的做一些优化工作, 而在实际的生产环境中是不会有此优化的。 如一个Jvm优化的例子

原始代码

        int a = 1;
        int b = 2;
        int sum = a + b;

        return sum;

可能直接优化为

        return 3;

所以最好使用更严谨的工具 来进行benchmark的工作,

Microbenchmarkings tools are intended to bring the JVM in "stable" state prior to executing tests and run your test suite for sufficient amount of time to get statistically proven evidence of the results.
摘自:http://www.buzdin.lv/2011/01/...

jmh就是这么一个工具

JMH is short for Java Microbenchmark Harness. JMH is a toolkit that helps you implement Java microbenchmarks correctly. JMH is developed by the same people who implement the Java virtual machine, so these guys know what they are doing.

jmh使用示例

使用jmh来对比BeanUtils和BeanCopier

代码

@State(Scope.Thread)
public class CopyPropertiesBenchmark {
  
    private UserModel model = new UserModel();
    private BeanCopier beanCopier = BeanCopier.create(UserModel.class, UserVo.class, false);

    /**
     * 人工setter复制属性
     *
     * @return
     */
    @Benchmark
    public UserVo manuallySetter() {
        UserVo vo = new UserVo();
        vo.setAvatar(model.getAvatar());
        vo.setNick(model.getNick());
        // ...

        return vo;
    }

    @Benchmark
    public UserVo beanUitls() {
        UserVo vo = new UserVo();
        BeanUtils.copyProperties(this.model, vo);
        return vo;
    }

    @Benchmark
    public UserVo beanCopier() {
        UserVo vo = new UserVo();
        beanCopier.copy(this.model, vo, null);
        return vo;
    }
}

运行结果

# JMH 1.14.1 (released 5 days ago)
# VM version: JDK 1.8.0_91, VM 25.91-b14
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/bin/java
# VM options: -server
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.zhugw.CopyPropertiesBenchmark.beanCopier

# Run progress: 0.00% complete, ETA 00:00:30
# Fork: 1 of 1
# Warmup Iteration   1: 70737107.801 ops/s
# Warmup Iteration   2: 63704495.294 ops/s
# Warmup Iteration   3: 112706026.910 ops/s
# Warmup Iteration   4: 113979995.875 ops/s
# Warmup Iteration   5: 114595368.349 ops/s
Iteration   1: 113207053.036 ops/s
Iteration   2: 111641520.705 ops/s
Iteration   3: 111258060.492 ops/s
Iteration   4: 110293317.399 ops/s
Iteration   5: 110773170.278 ops/s


Result "beanCopier":
  111434624.382 ±(99.9%) 4285987.844 ops/s [Average]
  (min, avg, max) = (110293317.399, 111434624.382, 113207053.036), stdev = 1113057.432
  CI (99.9%): [107148636.538, 115720612.226] (assumes normal distribution)

...

# Run complete. Total time: 00:00:32

Benchmark                                Mode  Cnt          Score          Error  Units
CopyPropertiesBenchmark.beanCopier      thrpt    5  111434624.382 ±  4285987.844  ops/s
CopyPropertiesBenchmark.beanUitls       thrpt    5    2451858.127 ±   525264.183  ops/s
CopyPropertiesBenchmark.manuallySetter  thrpt    5  103524264.901 ± 17644747.083  ops/s

从上面的结果可知BeanCopier的性能优于BeanUtils, 吞吐量差距约为45倍。

参考文档

http://tutorials.jenkov.com/j...
http://nitschinger.at/Using-J...
http://hg.openjdk.java.net/co...


zhuguowei2
825 声望26 粉丝