可以做动漫的网站/站长之家查询工具
去年,我们写过一篇关于JMH的入门使用的文章:Java基准测试工具JMH使用,今天我们再来聊一下关于JMH的高阶使用。主要我们会围绕着以下几点来讲:
- 对称并发测试
- 非对称并发测试
- 阻塞并发测试
- Map并发测试
关键词
@State 在很多时候我们需要维护一些状态内容,比如在多线程的时候我们会维护一个共享的状态,这个状态值可能会在每根线程中都一样,也有可能是每根线程都有自己的状态,JMH为我们提供了状态的支持。该注解只能用来标注在类上,因为类作为一个属性的载体。@State的状态值主要有以下几种:
Scope.Benchmark 该状态的意思是会在所有的Benchmark的工作线程中共享变量内容。
Scope.Group 同一个Group的线程可以享有同样的变量
Scope.Thread 每个线程都享有一份变量的副本,线程之间对于变量的修改不会相互影响
@Group 执行组的识别号
@GroupThreads 执行某个方法所需要的线程数量
对称并发测试
我们编写的所有基准测试都会被JMH框架根据方法名的字典顺序排序之后串行执行,然而有些时候我们会想要对某个类的读写方法并行执行,比如,我们想要在修改某个原子变量的时候又有其他线程对其进行读取操作。
@BenchmarkMode(Mode.AverageTime)
@Fork(1)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Group)
public class SymmetricBenchmark {private AtomicLong counter;@Setuppublic void init() {this.counter = new AtomicLong();}@GroupThreads(5)@Group("atomic")@Benchmarkpublic void inc() {this.counter.incrementAndGet();}@GroupThreads(5)@Group("atomic")@Benchmarkpublic long get() {return this.counter.get();}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(SymmetricBenchmark.class.getSimpleName()).build();new Runner(opt).run();}
}
结果为:
Benchmark Mode Cnt Score Error Units
SymmetricBenchmark.atomic avgt 5 0.126 ± 0.009 us/op
SymmetricBenchmark.atomic:get avgt 5 0.062 ± 0.011 us/op
SymmetricBenchmark.atomic:inc avgt 5 0.190 ± 0.011 us/op
我们在对AtomicLong进行自增操作的同时又会对其进行读取操作,这就是我们经常见到的高并发环境中某些API的操作方式,同样也是线程安全存在隐患的地方。5个线程对AtomicLong执行自增操作,5个线程对AtomicLong执行读取时的性能输出说明如下:
- group atomic(5个读线程,5个写线程)的平均响应时间为0.126 us,误差为0.009。
- group atomic(5个读线程)同时读取AtomicLong变量的速度为0.062 us,误差为0.011。
- group atomic(5个写线程)同时修改AtomicLong变量的速度为0.190 us,误差为0.011 。
非对称并发测试
有时,您需要达到非对称测试的目的。
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@State(Scope.Group)
public class AsymmetricBenchMark {private AtomicLong counter;@Setuppublic void up() {counter = new AtomicLong();}@Benchmark@Group("atomic")@GroupThreads(3)public long inc() {return counter.incrementAndGet();}@Benchmark@Group("atomic")@GroupThreads(1)public long get() {return counter.get();}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(AsymmetricBenchMark.class.getSimpleName()).build();new Runner(opt).run();}
}
结果为:
Benchmark Mode Cnt Score Error Units
AsymmetricBenchMark.atomic avgt 5 0.053 ± 0.003 us/op
AsymmetricBenchMark.atomic:get avgt 5 0.025 ± 0.006 us/op
AsymmetricBenchMark.atomic:inc avgt 5 0.062 ± 0.005 us/op
我们在对AtomicLong进行自增操作的同时又会对其进行读取操作,这就是我们经常见到的高并发环境中某些API的操作方式,同样也是线程安全存在隐患的地方。3个线程对AtomicLong执行自增操作,1个线程对AtomicLong执行读取时的性能输出说明如下:
- group atomic(1个读线程,3个写线程)的平均响应时间为0.053 us,误差为0.003 。
- group atomic(1个读线程)同时读取AtomicLong变量的速度为0.025 us,误差为0.006 。
- group atomic(3个写线程)同时修改AtomicLong变量的速度为0.062 us,误差为0.005 。
阻塞并发测试
有些时候我们想要执行某些容器的读写操作时可能会引起阻塞,比如blockqueue,在某些情况下程序会出现长时间的阻塞,这就严重影响了我们测试的结果,我们可以通过设置Options的timeout来强制让每一个批次的度量超时,超时的基准测试数据将不会被纳入统计之中。
以下测试,我们设置每批次如果超过10秒,就被认为超时不计入统计。
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Group)
public class InterruptBenchmark {private BlockingQueue<Integer> queue;private final static int VALUE = Integer.MAX_VALUE;@Setuppublic void init() {this.queue = new ArrayBlockingQueue<>(10);}@GroupThreads(5)@Group("queue")@Benchmarkpublic void put()throws InterruptedException {this.queue.put(VALUE);}@GroupThreads(5)@Group("queue")@Benchmarkpublic int take()throws InterruptedException {return this.queue.take();}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(InterruptBenchmark.class.getSimpleName())// 将每个批次的超时时间设置为10秒.timeout(TimeValue.milliseconds(10000)).build();new Runner(opt).run();}
}
结果为:
Benchmark Mode Cnt Score Error Units
InterruptBenchmark.queue avgt 5 19204.384 ± 23024.739 ns/op
InterruptBenchmark.queue:put avgt 5 14049.887 ± 49670.027 ns/op
InterruptBenchmark.queue:take avgt 5 24358.880 ± 31679.280 ns/op
有些执行时被阻塞的结果就被忽略了,报告中会如下所示:
Iteration 5: (benchmark timed out, interrupted 1 times) 27130.727 ±(99.9%) 53300.757 ns/op
如果超时时间设置得过小,那么,会得到如下警告:
# Timeout: 1000 ms per iteration, ***WARNING: The timeout might be too low!***
Map并发测试
对比几大线程安全Map的多线程下的读写性能,以后类似的操作可以按照这个模板来。
@Fork(1)
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Group)
public class MapBenchMark {@Param({"ConcurrentHashMap", "ConcurrentSkipListMap", "Hashtable", "Collections.synchronizedMap"})private String type;private Map<Integer, Integer> map;@Setuppublic void setUp() {switch (type) {case "ConcurrentHashMap":this.map = new ConcurrentHashMap<>();break;case "ConcurrentSkipListMap":this.map = new ConcurrentSkipListMap<>();break;case "Hashtable":this.map = new Hashtable<>();break;case "Collections.synchronizedMap":this.map = Collections.synchronizedMap(new HashMap<>());break;default:throw new IllegalArgumentException("Illegal map type.");}}@Group("map")@GroupThreads(5)@Benchmarkpublic void putMap() {int random = randomIntValue();this.map.put(random, random);}@Group("map")@GroupThreads(5)@Benchmarkpublic Integer getMap() {return this.map.get(randomIntValue());}/*** 计算一个随机值用作Map中的Key和Value** @return*/private int randomIntValue() {return (int) Math.ceil(Math.random() * 600000);}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(MapBenchMark.class.getSimpleName()).build();new Runner(opt).run();}
}
结果如下:
Benchmark (type) Mode Cnt Score Error Units
MapBenchMark.map ConcurrentHashMap thrpt 5 4903943.211 ± 208719.270 ops/s
MapBenchMark.map:getMap ConcurrentHashMap thrpt 5 2442687.631 ± 251150.685 ops/s
MapBenchMark.map:putMap ConcurrentHashMap thrpt 5 2461255.580 ± 260557.472 ops/s
MapBenchMark.map ConcurrentSkipListMap thrpt 5 3471371.602 ± 334184.434 ops/s
MapBenchMark.map:getMap ConcurrentSkipListMap thrpt 5 1710540.889 ± 196183.472 ops/s
MapBenchMark.map:putMap ConcurrentSkipListMap thrpt 5 1760830.713 ± 263480.175 ops/s
MapBenchMark.map Hashtable thrpt 5 1966883.854 ± 197740.289 ops/s
MapBenchMark.map:getMap Hashtable thrpt 5 676801.687 ± 71672.436 ops/s
MapBenchMark.map:putMap Hashtable thrpt 5 1290082.167 ± 174730.435 ops/s
MapBenchMark.map Collections.synchronizedMap thrpt 5 1976316.282 ± 99878.457 ops/s
MapBenchMark.map:getMap Collections.synchronizedMap thrpt 5 655744.125 ± 73634.788 ops/s
MapBenchMark.map:putMap Collections.synchronizedMap thrpt 5 1320572.158 ± 75428.848 ops/s
我们可以看到,在 putMap 和 getMap 方法中,通过随机值的方式将取值作为 key 和 value 存入 map 中,同样也是通过随机值的方式将取值作为 key 从 map 中进行数据读取(当然读取的值可能并不存在)。还有我们在基准方法中进行了随机值的运算,虽然随机值计算所耗费的CPU时间也会被纳入基准结果的统计中,但是每一个 map 都进行了相关的计算,因此,我们可以认为大家还是站在了同样的起跑线上,故而可以对其忽略不计。
基准测试的数据可以表明,在5个线程同时进行 map 写操作,5个线程同时进行读操作时,参数 type=ConcurrentHashMap 的性能是最佳的 。
下一篇,将和大家介绍下JMH的profiler
相关文章:

Java基准测试工具JMH高级使用
去年,我们写过一篇关于JMH的入门使用的文章:Java基准测试工具JMH使用,今天我们再来聊一下关于JMH的高阶使用。主要我们会围绕着以下几点来讲: 对称并发测试非对称并发测试阻塞并发测试Map并发测试 关键词 State 在很多时候我们…...

问心 | 再看token、session和cookie
什么是cookie HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。 什么是session Session 代表着服务器和客户端一次会话…...

Ubuntu 安装 CUDA and Cudnn
文章目录0 查看 nvidia驱动版本1 下载Cuda2 下载cudnn参考:0 查看 nvidia驱动版本 nvidia-smi1 下载Cuda 安装之前先安装 gcc g gdb 官方:https://developer.nvidia.com/cuda-toolkit-archive,与驱动版本进行对应,我这里是12.0…...

【漏洞复现】Grafana任意文件读取(CVE-2021-43798)
docker环境搭建 #进入环境 cd vulhub/grafana/CVE-2021-43798#启动环境,这个过程可能会有点慢,保持网络通畅 docker-compose up -d#查看环境 docker-compose ps直接访问虚拟机 IP地址:3000 目录遍历原理 目录遍历原理:攻击者可以通过将包含…...

磨金石教育摄影技能干货分享|春之旅拍
春天来一次短暂的旅行,你会选择哪里呢?春天的照片又该如何拍呢?看看下面的照片,或许能给你答案。照片的构图很巧妙,画面被分成两部分,一半湖泊,一半绿色树林。分开这些的是一条斜向的公路&#…...

中断以及 PIC可编程中断控制器
1 中断分为同步中断(中断)和异步中断(异常) 1.1 中断和异常的不同 中断由IO设备和定时器产生,用户的一次按键会引起中断。异步。 异常一般由程序错误产生或者由内核必须处理的异常条件产生。同步。缺页异常ÿ…...

SecureCRT 安装并绑定ENSP设备终端
软件下载链接链接:https://pan.baidu.com/s/1WFxmQgaO9bIiUTwBLSR4OA?pwd2023 提取码:2023 CRT安装:软件可以从上面链接进行下载,下载完成后解压如下:首先双击运行scrt-x64.8.5.4 软件,进行安装点击NEXT选…...

ESP32设备驱动-TCS3200颜色传感器驱动
TCS3200颜色传感器驱动 1、TCS3200介绍 TCS3200 和 TCS3210 可编程彩色光频率转换器在单个单片 CMOS 集成电路上结合了可配置的硅光电二极管和电流频率转换器。 输出是方波(50% 占空比),其频率与光强度(辐照度)成正比。 满量程输出频率可以通过两个控制输入引脚按三个预…...

< JavaScript小技巧:Array构造函数妙用 >
文章目录👉 Array构造函数 - 基本概念👉 Array函数技巧用法1. Array.of()2. Array.from()3. Array.reduce()4. (Array | String).includes()5. Array.at()6. Array.flat()7. Array.findIndex()📃 参考文献往期内容 💨今天这篇文章…...

【17】组合逻辑 - VL17/VL19/VL20 用3-8译码器 或 4选1多路选择器 实现逻辑函数
VL17 用3-8译码器实现全减器 【本题我的也是绝境】 因为把握到了题目的本质要求【用3-8译码器】来实现全减器。 其实我对全减器也是不大清楚,但是仿照对全加器的理解,全减器就是低位不够减来自低位的借位 和 本单元位不够减向后面一位索要的借位。如此而已,也没有很难理解…...

2023年全国最新二级建造师精选真题及答案19
百分百题库提供二级建造师考试试题、二建考试预测题、二级建造师考试真题、二建证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 37.下列纠纷中,属于劳动争议范围的有()。 A.因劳动保护发生的纠纷 B.家庭与家政…...

Java中的 this 和 super
1 this 关键字 1.1 this 访问本类属性 this 代表对当前对象的一个引用 所谓当前对象,指的是调用当前类中方法或属性的那个对象this只能在方法内部使用,表示对“调用方法的那个对象”的引用this.属性名,表示本对象自己的属性 当对象的属性和…...

ESP32设备驱动-红外寻迹传感器驱动
红外寻迹传感器驱动 1、红外寻迹传感器介绍 红外寻迹传感器具有一对红外线发射管与接收管,发射管发射出一定频率的红外线,当检测方向遇到障碍物(反射面)时,红外线反射回来被接收管接收,经过比较器电路处理之后,输出接口会输出一个数字信号(低电平或高电平,取决于电路…...

初识BFC
初识BFC 先说如何开启BFC: 1.设置display属性:inline-block,flex,grid 2.设置定位属性:absolute,fixed 3.设置overflow属性:hidden,auto,scroll 4.设置浮动…...

随想录二刷Day17——二叉树
文章目录二叉树9. 二叉树的最大深度10. 二叉树的最小深度11. 完全二叉树的节点个数12. 平衡二叉树二叉树 9. 二叉树的最大深度 104. 二叉树的最大深度 思路1: 递归找左右子树的最大深度,选择最深的 1(即加上当前层)。 class So…...

Weblogic管理控制台未授权远程命令执行漏洞复现(cve-2020-14882/cve-2020-14883)
目录漏洞描述影响版本漏洞复现权限绕过漏洞远程命令执行声明:本文仅供学习参考,其中涉及的一切资源均来源于网络,请勿用于任何非法行为,否则您将自行承担相应后果,本人不承担任何法律及连带责任。 漏洞描述 Weblogic…...

STM32F103CubeMX定时器
前言定时器作为最重要的内容之一,是每一位嵌入式软件工程师必备的能力。STM32F103的定时器是非常强大的。1,他可以用于精准定时,当成延时函数来使用。不过个人不建议这么使用,因为定时器很强大,这么搞太浪费了。如果想…...

多态且原理
多态 文章目录多态多态的定义和条件协变(父类和子类的返回值类型不同)函数隐藏和虚函数重写的比较析构函数的重写关键字final和override抽象类多态的原理单继承和多继承的虚函数表单继承下的虚函数表多继承下的虚函数表多态的定义和条件 定义࿱…...

动态库(二) 创建动态库
文章目录创建动态库设计动态库ABI兼容动态符号的可见性示例控制符号可见性通过-fvisibility通过strip工具删除指定符号创建动态库 在Linux中创建动态库通过如下过程完成: gcc -fPIC -c first.c second.c gcc -shared first.o second.o -o libdynamiclib.so 按照Li…...

opencv加水印
本文介绍opencv给图片加水印的方法。 目录1、添加水印1.1、铺满1.2、在指定区域添加1.3、一比一铺满1、添加水印 添加水印的原理是调低两张图片的透明度,然后叠加起来。公式如下: dst src1 * opacity src2 * (1 - opacity) gamma; opacity是透明度&a…...

Flume基操
Flume概述 Flume 定义 Flume 是 Cloudera 提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。Flume 基于流式架构,灵活简单。 Flume最主要的作用就是,实时读取服务器本地磁盘的数据,将数据写入到…...

图文详解红黑树,还有谁不会?
前言在MySQL中,无论是Innodb还是MyIsam,都使用了B树作索引结构(这里不考虑hash等其他索引)。本文将从最普通的二叉查找树开始,逐步说明各种树解决的问题以及面临的新问题,从而说明MySQL为什么选择B树作为索引结构。目录一、二叉查…...

多目标遗传算法NSGA-II原理详解及算法实现
在接触学习多目标优化的问题上,经常会被提及到多目标遗传算法NSGA-II,网上也看到了很多人对该算法的总结,但真正讲解明白的以及配套用算法实现的文章很少,这里也对该算法进行一次详解与总结。会有侧重点的阐述,不会针对…...

Spark 键值对RDD的操作
键值对RDD(Pair RDD)是指每个RDD元素都是(key,value)键值对类型,是一种常见的RDD类型,可以应用于很多的应用场景。 一、 键值对RDD的创建 键值对RDD的创建主要有两种方式: &#x…...

【SpringCloud】SpringCloud详解之Feign远程调用
目录前言SpringCloud Feign远程服务调用一.需求二.两个服务的yml配置和访问路径三.使用RestTemplate远程调用(order服务内编写)四.构建Feign(order服务内配置)五.自定义Feign配置(order服务内配置)六.Feign配置日志(oder服务内配置)七.Feign调优(order服务内配置)八.抽离Feign前…...

文档团队怎样使用GIT做版本管理
有不少小型文档团队想转结构化写作和发布,但是因为有限的IT技能和IT资源而受阻。本文为这样的小型文档团队而准备,描述怎样使用Git做内容的版本管理。 - 1 - 为什么需要版本管理 当一个团队进行协同创作内容时,有以下需要: 在对…...

【java】Java中-> 是什么意思?
先看一个例子 EventQueue.invokeLater(() -> {JFrame frame new ImageViewerFrame();frame.setTitle("ImageViewer");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}); // 上面那一段可以看成如下: EventQueue.invokeLater(ne…...

网络类型部分实验
1.实验思路: 首先用DHCP 给四台PC配置上地址,配置成功后 其次底层IP地址的下发完成的同时,进行检测是否可以ping通 接着进行R1和R5之间使用PPP的PAP认证,R5为主认证方 主认证方ISP 被认证方R1 其次进行R2和R5使用PPP的CHAP认证&am…...

java教程--函数式接口--lambda表达式--方法引用
函数式接口 介绍 jdk8新特性,只有一个抽象方法的接口我们称之为函数接口。 FunctionalInterface JDK的函数式接口都加上了FunctionalInterface 注解进行标识。但是无论是否加上该注解只要接口中只有一个抽象方法,都是函数式接口。 如在Comparato…...

java——代理
什么是代理: 给目标对象一个代理对象,由代理对象控制着对目标对象的引用 为什么使用代理: ①:功能增强:通过代理业务对原有业务进行增强 ②:用户只能同行过代理对象间接访问目标对象,防止用…...