橘子学JDK之JMH-03(@State)

这里我们来搞官方的第三个案例,引入新的注解@State。

一、案例三代码

package com.levi;/*** @Description:* @Author: Levi* @Date: 2024/4/8 18:44*/import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;// 预热注解,修改为只预热一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Warmup(iterations = 1,time = 1)
// 测试执行注解,修改为只执行一轮,每轮只跑一秒,默认是5,5这里改为1,1
@Measurement(iterations = 1,time = 1)
public class JMHSample_03_01_States {/** Most of the time, you need to maintain some state while the benchmark is* running. Since JMH is heavily used to build concurrent benchmarks, we* opted for an explicit notion of state-bearing objects.* 在 JMH(Java 微基准测试工具)中,执行基准测试过程中需要维护状态是很重要的,特别是对于并发基准测试。* JMH 提供了显式的状态对象概念来处理这一点。** Below are two state objects. Their class names are not essential, it* matters they are marked with @State. These objects will be instantiated* on demand, and reused during the entire benchmark trial.* 在您提供的代码片段中,有两个使用 @State 注解标记的状态对象。具体的类名并不重要,但 @State 注解是关键。* 这些对象将根据需要进行实例化,并在整个基准测试试验过程中重复使用。基准测试可以访问@State标注类的声明的变量** The important property is that state is always instantiated by one of* those benchmark threads which will then have the access to that state.* That means you can initialize the fields as if you do that in worker* threads (ThreadLocals are yours, etc).* 关键点是每个状态对象都是由其中一个基准测试线程实例化的。这确保了每个基准测试线程都可以访问自己的状态对象实例。* 因此,您可以像在工作线程中那样初始化状态对象的字段。这意味着您可以在状态对象中使用 ThreadLocal 或任何其他线程特定的构造。* 就是本地变量,线程安全。*/@State(Scope.Benchmark)public static class BenchmarkState {volatile double x = Math.PI;}@State(Scope.Thread)public static class ThreadState {volatile double x = Math.PI;}/** Benchmark methods can reference the states, and JMH will inject the* appropriate states while calling these methods. You can have no states at* all, or have only one state, or have multiple states referenced. This* makes building multi-threaded benchmark a breeze.* 基准方法可以引用这些状态,并且在调用这些方法时,JMH将注入适当的状态。您可以完全没有状态,或者只有一个状态,或者引用多个状态。* 这使得构建多线程基准测试变得非常简单。** For this exercise, we have two methods.* 对于这个练习,我们有两个方法。*/@Benchmarkpublic void measureUnshared(ThreadState state) {// All benchmark threads will call in this method.// 所有的测试线程都会调用这个方法// However, since ThreadState is the Scope.Thread, each thread,will have it's own copy of the state,// and this benchmark will measure unshared case.// 然而,由于ThreadState的作用域是Scope.Thread,每个线程将拥有自己的状态副本,因此这个基准将测量不共享状态的情况。// 也就是各自操作的对象是复制了一份,不是操作的共享变量,也就是线程安全。Scope.Thread作用域是在线程本地。// 换言之就是四个线程每个线程来调用的时候,都会自己创建一个ThreadState,不共享state.x++;}@Benchmarkpublic void measureShared(BenchmarkState state) {// All benchmark threads will call in this method.//所有基准线程都将调用此方法。// Since BenchmarkState is the Scope.Benchmark, all threads will share the state instance,// and we will end up measuring shared case.// 由于BenchmarkState的作用域是Scope.Benchmark,所有线程将共享状态实例,并且我们最终将测量共享情况。// 也就是测试启动的多个线程,是操作这个共享变量的Scope.Benchmark这个作用域是再所有的Benchmark方法的state.x++;}/** You are expected to see the drastic difference in shared and unshared cases,* because you either contend for single memory location, or not. This effect* is more articulated on large machines.* 预计会看到共享和非共享情况之间的显著差异,因为您要么竞争共享内存位置,也就是共享的时候存在并发竞争,不共享的不存在。* 这种效应在大型机器上更为显著。*/public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(JMHSample_03_01_States.class.getSimpleName()).threads(4) // 启动四个线程进行基准测试.forks(1).build();new Runner(opt).run();}}

二、@State

我们依然先不急着跑程序,我们看下这个代码。

@State(Scope.Benchmark)
public static class BenchmarkState {volatile double x = Math.PI;
}@State(Scope.Thread)
public static class ThreadState {volatile double x = Math.PI;
}

这里声明了两个类,一个是BenchmarkState ,他的注解是@State(Scope.Benchmark),他的作用范围是所有的Benchmark方法。
另一个是ThreadState ,他的注解是@State(Scope.Thread),他的作用范围是每个线程自己的。
然后呢,我们的两个基准测试方法。

@Benchmark
public void measureUnshared(ThreadState state)
这个方法的参数是哪个线程独享范围的state类。@Benchmark
public void measureShared(BenchmarkState state)
这个方法的参数是哪个所有Benchmark都共享的state类。

然后呢,我们会启动多个线程来启动基准测试,每个线程都会去调用这两个@Benchmark方法,不是一部分调一个,另一部分调另一个,是都会来调用。
只是调用的时候,Scope.Thread的那个类和他的变量会在每个线程都自己创建一个,他是不线程共享的。
而Scope.Benchmark这个类和他的变量是全局就一个,每个线程操作的是同一个。
所以就会产生一个结果就是:
@State(Scope.Benchmark)
public static class BenchmarkState {
volatile double x = Math.PI;
}这个方法其实是多线程竞争操作一个对象BenchmarkState的变量x,会产生并发竞争。

@State(Scope.Thread)
public static class ThreadState {
volatile double x = Math.PI;
}这个是多个线程操作的都是自己本地创建的。他们不存在并发竞争。

而且你会注意,他的每个变量x,都是加着volatile 的,他还要保证可见性在共享并发操作的时候。
现在你差不多明白了吧,这是个分别测试并发修改共享变量和每个线程各自改自己的本地变量的case。
那么不出意外的话,并发修改那指定效率不如那个共享的,因为有线程的切换,可见性的保证等等,cpu的竞争。

三、测试结果

在这里插入图片描述

四、@DefaultState

这个例子其实是官方文档的第四个例子,我们拿到这里,其实和上面那个一样的。只是这种把状态变量声明到自己本身里面了,没单独搞新的类。

package com.levi;/*** @Description:* @Author: Levi* @Date: 2024/4/8 19:23*/import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;/** Fortunately, in many cases you just need a single state object.* In that case, we can mark the benchmark instance itself to be* the @State. Then, we can reference its own fields as any* Java program does.* 幸运的是,在许多情况下,您只需要一个单独的状态对象。在这种情况下,我们可以将基准测试实例本身标记为 @State。* 然后,我们可以像任何 Java 程序那样引用它自己的字段。其实就是把原来单独声明变量的类,现在是放在自己本身里面当成一个变量。这里也可以搞多个,你可以再写个y,不是只能写一个x。* */@State(Scope.Thread)// 这里也可以标记,表示这个状态值是线程独享,也就是每个线程都创建
public class JMHSample_04_01_DefaultState {double x = Math.PI;/**这里就等价于下面,只是没有这个语法而已。@Benchmarkpublic void measure(JMHSample_04_01_DefaultState state) {state.x++;}*/@Benchmarkpublic void measure() {x++;}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(JMHSample_04_01_DefaultState.class.getSimpleName()).forks(1).build();new Runner(opt).run();}}

五、总结

没总结的,注释非常明确了。

六、参考链接

1、JMH官方文档
2、JMH官方文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/800624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【YOLOV8】项目目录重点部分介绍和性能评估指标

目录 一 项目目录重点部分介绍 二 性能评估指标 一 项目目录重点部分介绍 1 ultralytics

windows环境变量滥用维权/提权

0x01 前提 通过滥用系统的路径搜索机制来欺骗高权限用户执行看似合法的系统二进制文件,实际上是恶意的代码或程序,从而导致升权限并执行恶意操作。 攻击的关键前提: 路径搜索顺序: 当用户在命令行或程序中执行一个命令时&#x…

kafka 高吞吐设计分析

说明 本文基于 kafka 2.7 编写。author blog.jellyfishmix.com / JellyfishMIX - githubLICENSE GPL-2.0 概括 支撑 kafka 高吞吐的设计主要有以下几个方面: 网络 nio 主从 reactor 设计模式 顺序写。 零拷贝。 producer producer 开启压缩后是批量压缩,bro…

【Qt】:常用控件(七:输入类控件)

常用控件 一.Combo Box(下拉框)二.Spin Box(微调框)三.ate Edit&Time Edit(日期微调框)四.Dial(旋钮)五.Slider(滑动条) 一.Combo Box(下拉框…

738.单调递增的数字

// 定义一个名为Solution的类 class Solution { public:// 定义公共成员函数:计算并返回大于等于输入整数N且其各位数字非降序排列的最小整数int monotoneIncreasingDigits(int N) {// 将整数N转换成字符串形式,方便操作每一位数字string strNum to_str…

23linux 自定义shell文件系统

打印环境变量,把当前子进程所有环境变量打印出来 环境变量也是一张表(指针数组以null结尾,最后条件不满足就退出了 ) 用子进程调用 结论1 当我们进行程序替换的时候 ,子进程对应的环境变量(子进程的环境变…

Mybatis执行器(Executor)

Executor简介 Executor Executor是MyBatis的核心接口之一,其中定义了数据库操作的基本方法。在实际应用中经常涉及的SqlSession接口的功能,都是基于Executor接口实现的。 BaseExecutor BaseExecutor是一个实现了Executor接口的抽象类,它实现了Execut…

Yolov8-pose关键点检测:特征融合 | CAMixing:卷积-注意融合模块和多尺度提取能力 | 2024年4月最新成果

💡💡💡本文独家改进:CAMixingBlock更好的提取全局上下文信息和局部特征,包括两个部分:卷积-注意融合模块和多尺度前馈网络; 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特征的提取能力;2)放在detect前面,增强detect提取能力; 提供多种改进方…

【MATLAB源码-第180期】基于matlab的PTS,SLM,CPFilter三种降低OFDM系统的PAPR仿真。

操作环境: MATLAB 2022a 1、算法描述 1. 限幅和滤波(Clipping and Filtering) 原理简介 限幅和滤波是一种基础且直观的方法,用于降低OFDM信号的PAPR。在限幅阶段,信号的幅度在达到设定阈值时会被削减,…

皮具5G智能制造工厂数字孪生可视化平台,推进企业数字化转型

皮具5G智能制造工厂数字孪生可视化平台,推进企业数字化转型。随着信息技术的快速发展,数字化转型已成为企业提升竞争力、实现可持续发展的关键路径。皮具行业,作为一个传统的手工制造业,正面临着巨大的市场变革和技术挑战。如何在…

红队打靶:holynix打靶流程-文件包含-文件上传-修改伪设备提权(vulnhub)

目录 开头 1.主机发现和端口扫描 2.80端口-万能密码-文件泄露 sql注入万能密码 文件泄露-读取/etc/passwd文件 sqlmap POST注入| SQL注入实现越权 | 水平越权 最后构造的sql语句,为什么这么构造嘞? 3.文件上传、文件解析漏洞利用 浏览器怎么访问家目录啊&…

C语言指针—指针和指针类型

指针是什么? 指针是什么? 指针理解的2个要点: 指针是内存中一个最小单元的编号,也就是地址 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量 总结:指针就是地址,口…

Windows深度学习环境----Cuda version 10.2 pytorch3d version 0.3.0

Requirements Python version 3.8.5Pytorch version: pytorch1.6.0 torchvision0.8.2 torchaudio0.7.0 cudatoolkit10.2.89pytorch3d version 0.3.0Cuda version 10.2 感觉readme文件里的不适配,跟pytorch官网不同 以前的 PyTorch 版本 |PyTorch的 # CUDA 10.2 c…

充电桩项目,开源啦!

好,我是田哥 很多人,最近都在关注我的充电桩项目,之前建了一个微服务架构的项目,也有单体项目的代码开源。 今天,我把最新版微服务架构的充电桩项目源代码开源。 充电桩的输入端与交流电网直接连接,输出端都…

WindowServer2019远程桌面无法连接问题及处理方法

WindowServer2019远程桌面无法连接问题及处理方法 文章目录 WindowServer2019远程桌面无法连接问题及处理方法1. 问题描述1. 连接问题2. 原因分析 2. 解决方法1. 零时解决方法2. 永久解决方法1. 打开注册表编辑器2. GracePeriod的权限权限设置3. 删除REG_BINARY4. 重启 1. 问题…

VMware配置环境(安装运行问题)及系列dns端口网络类型IP远程连接学习之(详谈8000字)

安装vmware快速配置步骤 下载VMware安装包 在下载好VMware安装包之后双击运行 接受条款 关闭VMware自动更新 勾选快捷键方式 安装VMware安装 输入许可证(有需要私信小编) 安装完成 重启电脑即可 最终成功界面: 安装Linux系统 创建虚拟机 选择…

基于springboot+vue+Mysql的滴答拍摄影项目

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…

Windows远程执行

Windows远程执行 前言 1、在办公环境中,利用系统本身的远程服务进行远程代码执行甚至内网穿透横向移动的安全事件是非常可怕的,因此系统本身的一些远程服务在没有必要的情况下建议关闭,防止意外发生; 2、作为安全人员&#xff0…

easyexcel处理复杂表头

需求&#xff0c;模板如下 功能如下 开始整活&#xff0c;依赖包。 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.1</version> </dependency>下载导入模板 1.方法 GetMapping…