JHM是openJDK开发的一个benchmark框架。它是一个Maven依赖,所以创建一个Maven项目,引入下面两个依赖:

    <dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
</dependency>

两个依赖版本一样,版本号你可以去中心仓库查一下最新的,目前是1.37

然后就可以写一个测试类,比如我想对比一下ArrayListLinkedList哪个性能好:

你猜哪个性能好?你可能会说给中间插入值链表更快,但是怎么知道插入到哪里呢...

基准配置

我的测试类叫MyBenchmark,在main方法中配置如下:

    public static void main(String[] args) throws RunnerException {
System.out.println("Hello World!");
Options options = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
// 这里需要include测试类进来,使用simpleName就行
.forks(1)
// forks是启动几个JVM实例,每个实例单独测试,配置1就行
.timeout(TimeValue.seconds(10))
// timeout指定下面配置的每一次测试的超时时间,你可以改大一些
.threads(1)
// 线程数是同时用几个线程跑测试代码,比如我的笔记本是6核12线程的,3线程反而最好
.warmupIterations(1)
// 正式测试前跑几次热身。和正式测试流程一样,只是数据不计入统计结果
.warmupTime(TimeValue.seconds(10))
// 预热多久
.measurementTime(TimeValue.seconds(2))
// 正式测试每次多久
.measurementIterations(5)
// 测试几轮
.build(); new Runner(options).run();
}

Round One

第一轮测试代码如下:


public class MyBenchmark {
private static final int limit = 10_0000;
@Benchmark
public void testArrayList() {
List<Integer> list = new ArrayList<>(1);
for (int i = 0; i < limit; i++) {
list.add(i);
}
if (false) {
System.out.println("more");
}
} @Benchmark
public void testLinkedList() {
List<Integer> list = new LinkedList<>();
for (int i = 0; i < limit; i++) {
list.add(i);
}
if (false) {
System.out.println("more");
}
}
}

给每个集合中加入10万个数,看每秒能执行多少次。你先猜一下结果。

执行main方法,会打印出配置信息,比如

# JMH version: 1.37
# VM version: JDK 21.0.1, Java HotSpot(TM) 64-Bit Server VM, 21.0.1+12-jvmci-23.1-b19
# VM invoker: /.sdkman/candidates/java/21.0.1-graal/bin/java
# VM options: -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCIProduct -XX:-UnlockExperimentalVMOptions -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=53238:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
# Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable)
# Warmup: 1 iterations, 10 s each
# Measurement: 5 iterations, 2 s each
# Timeout: 10 s per iteration, ***WARNING: The timeout might be too low!***
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time

测试结果:

Benchmark                    Mode  Cnt     Score      Error  Units
MyBenchmark.testArrayList thrpt 5 1286.969 ± 1686.876 ops/s
MyBenchmark.testLinkedList thrpt 5 1909.538 ± 373.143 ops/s

数组每秒1000多次(每次插入10万数据),链表每秒快2000次了。链表取胜!

如果数据改成1000个,结果是

Benchmark                    Mode  Cnt       Score       Error  Units
MyBenchmark.testArrayList thrpt 5 174194.500 ± 19431.634 ops/s
MyBenchmark.testLinkedList thrpt 5 169880.651 ± 74638.041 ops/s

数组险胜。

Round Two

这次把其中的操作改成排序,每插入一个数就进行一个倒序排序:

            list.add(i);
list.sort(Comparator.reverseOrder());// 使用逆序,让他一定要移动数据

你猜结果如何?

先看1万个数据(10万的话我电脑可能完不成):

Benchmark                    Mode  Cnt  Score   Error  Units
MyBenchmark.testArrayList thrpt 5 4.867 ± 2.272 ops/s
MyBenchmark.testLinkedList thrpt 5 0.638 ± 1.323 ops/s

数组完胜!

再看100个数据:

Benchmark                    Mode  Cnt      Score       Error  Units
MyBenchmark.testArrayList thrpt 5 79449.678 ± 97210.639 ops/s
MyBenchmark.testLinkedList thrpt 5 32889.346 ± 2018.265 ops/s

数组还是比链表优势大很多。

Round Three

这次往中间插入值:

            list.add(i/2, 1);
// list.sort(Comparator.reverseOrder());

看10万数据的结果就行了,你猜结果啥样:

Benchmark                    Mode  Cnt  Score   Error  Units
MyBenchmark.testArrayList thrpt 5 3.606 ± 2.153 ops/s
MyBenchmark.testLinkedList thrpt 5 0.151 ± 0.112 ops/s

不说了,我要去删掉我之前代码中的链表了。

java中的基准测试框架JMH的更多相关文章

  1. 如何在Java中做基准测试?JMH使用初体验

    大家好,我是王有志,欢迎和我聊技术,聊漂泊在外的生活.快来加入我们的Java提桶跑路群:共同富裕的Java人. 最近公司在搞新项目,由于是实验性质,且不会直接面对客户的项目,这次的技术选型非常激进,如 ...

  2. 菜鸟日记之 java中的集合框架

    java中的集合框架图 如图所示:java中的集合分为两种Collection和Map两种接口 可分为Collection是单列集合和Map的双列集合 Collection单列集合:继承了Iterat ...

  3. Java中的集合框架(上)

    Java中的集合框架概述 集合的概念: Java中的集合类:是一种工具类,就像是容器,存储任意数量的具有共同属性的对象. 集合的作用: 1.在类的内部,对数据进行组织: 2.简单的快速的搜索大数据量的 ...

  4. Java中的集合框架-Collections和Arrays

    上一篇<Java中的集合框架-Map>把集合框架中的键值对容器Map中常用的知识记录了一下,本节记录一下集合框架的两个工具类Collections和Arrays 一,Collections ...

  5. Java中的集合框架-Map

    前两篇<Java中的集合框架-Commection(一)>和<Java中的集合框架-Commection(二)>把集合框架中的Collection开发常用知识点作了一下记录,从 ...

  6. Java中的集合框架-Collection(二)

    上一篇<Java中的集合框架-Collection(一)>把Java集合框架中的Collection与List及其常用实现类的功能大致记录了一下,本篇接着记录Collection的另一个子 ...

  7. Java中的集合框架

    概念与作用 集合概念 现实生活中:很多事物凑在一起 数学中的集合:具有共同属性的事物的总体 java中的集合类:是一种工具类,就像是容器,储存任意数量的具有共同属性的对象 在编程时,常常需要集中存放多 ...

  8. java 中的 viewUtils框架

    IoC的概念介绍 控制反转(IOC)模式(又称DI:Dependency Injection)就是Inversion of Control,控制反转.在Java开发中,IoC意 味着将你设计好的类交给 ...

  9. Java中的集合框架(下)

    学生选课--判断Set中课程是否存在 package com.imooc.collection; import java.util.ArrayList; import java.util.Arrays ...

  10. Java中的三大框架分别有什么用

    一.Spring Spring是一个解决了许多在J2EE开发中常见的问题的强大框架. Spring提供了管理业务对象的一致方法并且鼓励了注入对接口编程而不是对类编程的良好习惯.Spring的架构基础是 ...

随机推荐

  1. vue3语法糖script setup

    在vue3种setup的写法,可以单独写setup()也可以写到script标签中,当然我们推荐后面这种 他的好处有很多,代码也简洁很多. 1.属性和方法无需return,可直接使用 /*原先*/ & ...

  2. mac + docker+单击clickhouse+Dbeaver安装全套

    一.保证docker安装成功 看下教程:https://www.runoob.com/docker/macos-docker-install.html 二.启动桌面版docker 三.下载clickh ...

  3. k8s快捷命令

    查看node使用率: for i in `kubectl get nodes|awk '{print $1}'|sed '1d'`;do  echo "=========>" ...

  4. smtplib详解,发送邮件

    创建邮箱账号 1.官网登录邮箱. 2.在邮箱的主界面找到"设置",新版的主界面与旧版稍有不同,一般位于上方,齿轮状的即是. 3.点击齿轮状的设置标志,会弹出一个下拉菜单,在最后有我 ...

  5. 如何利用 Seaborn 实现高级统计图表

    本文分享自华为云社区<使用 Seaborn 实现高级统计图表从箱线图到多变量关系探索> ,作者:柠檬味拥抱. 在数据科学和数据可视化领域,Seaborn 是一个备受欢迎的 Python 可 ...

  6. Web Service和Web API理解和使用场景

    Web Service 理解:Web Service 是一种基于网络的服务,它使用标准化的消息传递协议,最典型的是基于 SOAP(Simple Object Access Protocol)协议.SO ...

  7. 莫烦tensorflow学习记录 (5)什么是过拟合 (Overfitting)

    什么是过拟合 (Overfitting) 莫烦讲的非常通俗易懂可以看看https://mofanpy.com/tutorials/machine-learning/tensorflow/intro-o ...

  8. ReplayKit2:声音回调时间戳问题

    一.ReplayKit2 框架回调中 视频.micphone声音.系统声音三路回调 - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffe ...

  9. webpack配置图片处理

    # 安装 npm i -D url-loader html-loader file-loader # loader配置 module: { rules: [ // 图片处理 { test: /\.(p ...

  10. 设定cookie 获取cookie数据的转换

    1,cookie必须是键值对形式的               键名=数值               而且必须是 字符串格式               document.cookie = 'nam ...