登峰造极境

  • WIN
    • CSharp
    • JAVA
    • OAM
    • DirectX
    • Emgucv
  • UNIX
    • FFmpeg
    • QT
    • Python
    • Opencv
    • Openwrt
    • Twisted
    • Design Patterns
    • Mysql
    • Mycat
    • MariaDB
    • Make
    • OAM
    • Supervisor
    • Nginx
    • KVM
    • Docker
    • OpenStack
  • WEB
    • ASP
    • Node.js
    • PHP
    • Directadmin
    • Openssl
    • Regex
  • APP
    • Android
  • AI
    • Algorithm
    • Deep Learning
    • Machine Learning
  • IOT
    • Device
    • MSP430
  • DIY
    • Algorithm
    • Design Patterns
    • MATH
    • X98 AIR 3G
    • Tucao
    • fun
  • LIFE
    • 美食
    • 关于我
  • LINKS
  • ME
Claves
长风破浪会有时,直挂云帆济沧海
  1. 首页
  2. Platforms
  3. WINDOWS
  4. JAVA
  5. 正文

JMH: Java基准测试工具套件

2022-03-29
源链接:https://www.jianshu.com/p/0da2988b9846

JMH简介
官网:http://openjdk.java.net/projects/code-tools/jmh/

简介:JMH is a Java harness for building, running, and analysing nano/micro/milli/macro benchmarks written in Java and other languages targetting the JVM,由简介可知,JMH不止能对Java语言做基准测试,还能对运行在JVM上的其他语言做基准测试。而且可以分析到纳秒级别。

推荐用法
官方推荐创建一个独立的Maven工程来运行JMH基准测试,这样更能确保结果的准确性。当然也可以在已存在的工程中,或者在IDE上运行,但是越复杂,结果越不可靠(more complex and the results are less reliable)。

简单实用
推荐用法通过命令行创建,构建和运行JMH基准测试。

JMH和jMeter的不同
JMH和jMeter的使用场景还是有很大的不同的,jMeter更多的是对rest api进行压测,而JMH关注的粒度更细,它更多的是发现某块性能槽点代码,然后对优化方案进行基准测试对比。比如json序列化方案对比,bean copy方案对比,文中提高的洗牌算法对比等。

setup
生成一个新的JMH工程的maven命令如下:

压测代码
默认生成的MyBenchmark.java源码如下,testMethod()中就是你要压测的代码,下面是笔者要压测的洗牌算法:

@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {

    @GenerateMicroBenchmark
    public List<Integer> testMethod() {
        int cardCount = 54;
        List<Integer> cardList = new ArrayList<Integer>();
        for (int i=0; i<cardCount; i++){
            cardList.add(i);
        }
        // 洗牌算法
        Random random = new Random();
        for (int i=0; i<cardCount; i++) {
            int rand = random.nextInt(cardCount);
            Collections.swap(cardList, i, rand);
        }
        return cardList;
    }

}

build
写完代码接下来就是构建并打包,在pom.xml所在目录执行如下命令:

mvn clean package

run

java -jar target/microbenchmarks.jar

输出结果:

# Run progress: 0.00% complete, ETA 00:00:10
# VM invoker: C:\Program Files\Java\jre1.8.0_181\bin\java.exe
# VM options: <none>
# Fork: 1 of 1
# Warmup: 5 iterations, 1 s each
# Measurement: 5 iterations, 1 s each
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.afei.jmh.MyBenchmark.testMethod
# Warmup Iteration   1: 1133.738 ns/op
# Warmup Iteration   2: 1169.750 ns/op
# Warmup Iteration   3: 1066.204 ns/op
# Warmup Iteration   4: 1086.300 ns/op
# Warmup Iteration   5: 1145.228 ns/op
Iteration   1: 1045.157 ns/op
Iteration   2: 1064.303 ns/op
Iteration   3: 1064.227 ns/op
Iteration   4: 1053.979 ns/op
Iteration   5: 1055.718 ns/op

Result : 1056.677  ±(99.9%) 30.809 ns/op
  Statistics: (min, avg, max) = (1045.157, 1056.677, 1064.303), stdev = 8.001
  Confidence interval (99.9%): [1025.868, 1087.486]

Benchmark                        Mode   Samples         Mean   Mean error    Units
c.a.j.MyBenchmark.testMethod     avgt         5     1056.677       30.809    ns/op

参数解读:

@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)。所以,基准测试后对代码预热总计5秒(迭代5次,每次1秒)。预热对于压测来说非常非常重要,如果没有预热过程,压测结果会很不准确。

@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS),表示循环运行5次,总计5秒时间。

@Fork这个注解表示fork多少个线程运行基准测试,如果@Fork(1),那么就是一个线程,这时候就是同步模式。

基准测试模式申明为:@BenchmarkMode(Mode.AverageTime)搭配@OutputTimeUnit(TimeUnit.NANOSECONDS)(可选基准测试模式通过枚举Mode得到),笔者的示例是AverageTime,即表示每次操作需要的平均时间,而OutputTimeUnit申明为纳秒,所以基准测试单位是ns/op,即每次操作的纳秒单位平均时间。

标签: 暂无
最后更新:2022-03-29

代号山岳

知之为知之 不知为不知

点赞
< 上一篇
下一篇 >

COPYRIGHT © 2099 登峰造极境. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

蜀ICP备14031139号-5

川公网安备51012202000587号