JMH微基准测试框架学习笔记

一、简介

JMH(Java Microbenchmark Harness)是一个用于编写、构建和运行Java微基准测试的框架。它提供了丰富的注解和工具,用于精确控制测试的执行和结果测量,从而帮助我们深入了解代码的性能特性。

二、案例实战

  1. 在你的pom文件中导入如下依赖:
        <dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.21</version></dependency><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.21</version></dependency>

要使用JMH进行微基准测试,你需要在项目的构建系统(如Maven或Gradle)中引入JMH的依赖。

  1. 便携示例代码

下面是一个简单的JMH测试示例,用于比较直接访问数组元素和通过方法访问数组元素的性能差异。

package cn.pottercoding.jmh;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;import java.util.concurrent.TimeUnit;/*** @author Mr.Sun* @since 2024年03月20日** 一个简单的JMH测试示例,用于比较直接访问数组元素和通过方法访问数组元素的性能差异。*/
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class ArrayAccessBenchmark {// 数组大小private static final int ARRAY_SIZE = 10000;// 初始化数组private int[] array = new int[ARRAY_SIZE];// 初始化方法,用于填充数组@Setuppublic void setup() {for (int i = 0; i < ARRAY_SIZE; i++) {array[i] = i;}}// 直接访问数组元素@Benchmarkpublic int directAccess() {int sum = 0;for (int i = 0; i < ARRAY_SIZE; i++) {sum += array[i];}return sum;}// 通过方法访问数组元素@Benchmarkpublic int methodAccess() {int sum = 0;for (int i = 0; i < ARRAY_SIZE; i++) {sum += getElement(i);}return sum;}// 获取数组元素的方法private int getElement(int index) {return array[index];}// 主方法,用于运行基准测试public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(ArrayAccessBenchmark.class.getSimpleName()).build();new Runner(opt).run();}
}

接下来让我们一起看下上面示例代码中用到的每个JMH注解的含义:

  1. @BenchmarkMode
    这个注解用于指定基准测试的模式。Mode.AverageTime表示测量的是每次操作的平均执行时间。JMH提供了多种模式,如Throughput(吞吐量,即每秒完成的操作数)和SampleTime(采样时间)等。

  2. @Warmup@Measurement
    @Warmup:用于指定预热阶段的相关设置。预热阶段用于让JVM的JIT编译器有时间优化测试代码,并使得缓存、垃圾回收等达到稳定状态。iterations指定预热迭代的次数,time和timeUnit分别指定预热阶段的总时间和时间单位。
    @Measurement:用于指定实际测量阶段的相关设置。这些设置类似于预热阶段,但它们是用于收集基准测试结果的。

  3. @State
    这个注解用于定义测试状态。Scope.Thread表示每个测试线程都有自己的测试状态实例。这样可以避免多线程之间的状态共享问题。其他可能的范围还包括Scope.Benchmark(所有线程共享同一个状态实例)和Scope.Group(每个测试组共享一个状态实例)。

  4. @OutputTimeUnit
    这个注解用于指定输出结果的时间单位。在这个例子中,TimeUnit.NANOSECONDS表示输出的时间将以纳秒为单位。

  5. @Setup
    这个注解用于标记在每次基准测试方法运行之前应该执行的方法。它通常用于初始化测试所需的数据或状态。在这个例子中,setup()方法用于填充数组。

  6. @Benchmark
    这个注解用于标记一个基准测试方法。JMH会运行这个方法多次,并收集相关的性能数据。在这个例子中,directAccess()methodAccess()都是基准测试方法,它们分别测试直接访问数组元素和通过方法访问数组元素的性能。

  7. @Param
    虽然这个注解在上面的示例代码中并没有使用,但它是一个常见的JMH注解,用于参数化基准测试。通过在测试类中的字段上使用@Param注解,并指定不同的值,你可以为同一个基准测试方法创建多个不同的测试场景。

执行结果如下:
在这里插入图片描述

代码执行结果分析:

  1. directAccess() 方法
    这个方法直接通过数组索引访问数组元素,并计算它们的和。由于它直接操作数组的内存位置,因此通常是最快的访问方式。在大多数情况下,directAccess() 方法应该会获得较低的平均执行时间。

  2. methodAccess() 方法
    这个方法通过调用 getElement() 方法来访问数组元素。虽然getElement()方法内部也是直接访问数组,但是方法调用的开销(如参数传递、栈帧创建等)通常会比直接访问要高一些。因此,methodAccess() 方法的平均执行时间很可能会比 directAccess() 方法稍长。

  3. 结果比较
    JMH会运行每个基准测试方法多次,并收集每次运行的执行时间。然后,它会计算这些时间的平均值、标准差等统计信息,并将它们输出到控制台或文件中。

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

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

相关文章

MySQL 排序的那些事儿

书接上回 上次发了几张图&#xff0c;给了几个MySQL Explain的场景&#xff0c;链接在这儿&#xff1a;你是不是MySQL老司机&#xff1f;来看看这些explain结果你能解释吗&#xff1f;MySQL 夺命6连问 我们依次来分析下这6个问题。 在分析之前&#xff0c;我们先来了解一下M…

操作系统面经-用户态和内核态

字节实习生带你面试&#xff0c;后台私信可以获得面试必过大法&#xff01;&#xff01; 根据进程访问资源的特点&#xff0c;我们可以把进程在系统上的运行分为两个级别&#xff1a; 用户态(User Mode) : 用户态运行的进程可以直接读取用户程序的数据&#xff0c;拥有较低的…

【蓝牙协议栈】【BLE】低功耗蓝牙配对绑定过程分析(超详细)

1. 精讲蓝牙协议栈&#xff08;Bluetooth Stack&#xff09;&#xff1a;SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅&#xff0c;【蓝牙协议栈】和【Android Bluetooth Stack】专栏会持续更新中.....敬请期待&#xff01…

Three.js 中的 OrbitControls 是一个用于控制相机围绕目标旋转以及缩放、平移等操作的控制器。

demo案例 Three.js 中的 OrbitControls 是一个用于控制相机围绕目标旋转以及缩放、平移等操作的控制器。下面是它的详细讲解&#xff1a; 构造函数: OrbitControls(object: Camera, domElement?: HTMLElement)object&#xff1a;THREE.Camera 实例&#xff0c;控制器将围绕…

从零开始学习在VUE3中使用canvas(五):globalCompositeOperation(图形混合)

一、简介 通过设置混合模式来改变图像重叠区域的显示方式。 const ctx canvas.getContext("2d");ctx.globalCompositeOperation "source-over"; 二、属性介绍 source-over 这是默认的复合操作。将源图像绘制到目标图像上&#xff0c;保留目标图像的不透…

IPV6协议之DHCPV6

目录 背景&#xff1a; 一、DHCPV6概述 DHCPv6 Client&#xff1a; DHCPv6 Relay&#xff1a; DHCPv6 Server&#xff1a; 二、DHCPV6工作原理 DHCPV6无状态自动分配 三、DHCP基础配置 服务端 四、DHCPV6地址更新时间&#xff08;DHCPV4租期&#xff09; 五、DHCPV6…

idea 开发serlvet篮球秩序册管理系统idea开发mysql数据库web结构计算机java编程layUI框架开发

一、源码特点 idea开发 java servlet 篮球秩序册管理系统是一套完善的web设计系统mysql数据库 系统采用serlvetdaobean mvc 模式开发&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 servlet 篮…

☆【前后缀】【双指针】Leetcode 42. 接雨水

【前后缀】【双指针】Leetcode 42. 接雨水 解法1 前后缀分解解法2 双指针 ---------------&#x1f388;&#x1f388;42. 接雨水 题目链接&#x1f388;&#x1f388;------------------- 解法1 前后缀分解 维护一个前缀&#xff08;左侧最高&#xff09;后缀&#xff08;右侧…

【Linux系统编程(进程编程)】进程的退出:父进程等待子进程的退出之僵尸进程与孤儿进程

文章目录 一、进程退出1.1、进程正常退出方式1.2、异常退出 二、父进程等待子进程退出&#xff08;一&#xff09;2.1、为什么要等待子进程退出2.2、&#xff08;1&#xff09;父进程等待子进程退出并收集子进程的退出状态如何等待wstatus空wstatus非空 2.3、&#xff08;2&…

LeetCode---389周赛

题目列表 3083. 字符串及其反转中是否存在同一子字符串 3084. 统计以给定字符开头和结尾的子字符串总数 3085. 成为 K 特殊字符串需要删除的最少字符数 3086. 拾起 K 个 1 需要的最少行动次数 一、字符串及其反转中是否存在同一子字符串 直接暴力枚举即可&#xff0c;代码…

【PHP + 代码审计】数组函数

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

力扣面试150 x 的平方根 二分 换底法 牛顿迭代法 一题多解

Problem: 69. x 的平方根 思路 &#x1f468;‍&#x1f3eb; 参考题解 &#x1f496; 袖珍计算器算法 class Solution {public int mySqrt(int x){if (x 0)return 0; // Math.exp(3)&#xff1a;e的三次方int ans (int) Math.exp(0.5 * Math.log(x));return (long) (an…

配置环境安装包遇到的问题

1. error: could not install packages due to an oserror: [errno 28] no space left on device 说是磁盘占用过多&#xff0c;查看磁盘占用情况。 df -h 果然占比100% 清理了众多缓存.cache都不行&#xff0c;而且其他利用率很低&#xff0c;可能是pip install的过程中使…

qt 实现 轮播图效果,且还有 手动 上一页和下一页 已解决

QT中有 轮播图的需求&#xff0c;按照正常html版本 。只需要配置数组就能搞定&#xff0c;但是c qt版本 应该用什么了。 第一想到的是采用定时器。 // 定时器初始化{m_pTime new QTimer(this);m_pTime->start(4 * 1000);//启动定时器并设置播放时间间隔m_pAutoFlag true;/…

【python】python turtle绘制坤坤打球

一、效果图&#xff1a; 二、准备工作 &#xff08;1)、导入必要的模块&#xff1a; 代码首先导入了需要使用的模块&#xff1a;requests、lxml和csv。 import requests from lxml import etree import csv 如果出现模块报错 进入控制台输入&#xff1a;建议使用国内镜像源 p…

智慧公厕:跨界融合,打造智慧城市新名片

随着城市化进程的不断加快&#xff0c;公共厕所建设成为一个亟待解决的问题。传统的公厕存在着管理繁琐、卫生差、服务不到位等一系列问题&#xff0c;与城市发展的节奏不协调。为此&#xff0c;推进新型智慧公厕建设成为了一个重要的解决方案。智慧公厕的建设需要推进技术融合…

【论文精读】VIT:vision transformer论文

相关文章 【论文精读】Transformer&#xff1a;Attention Is All You Need 文章目录 相关文章一、文章概览&#xff08;一&#xff09;研究背景&#xff08;二&#xff09;核心思路&#xff08;三&#xff09;相关工作&#xff08;三&#xff09;文章结论 二、模型细节&#x…

【MySQL系列】优化数据库时区设置,确保数据一致性与准确性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

图论基础|深度优先dfs、广度优先bfs

dfs 与 bfs 区别 提到深度优先搜索&#xff08;dfs&#xff09;&#xff0c;就不得不说和广度优先搜索&#xff08;bfs&#xff09;有什么区别 先来了解dfs的过程&#xff0c;很多录友可能对dfs&#xff08;深度优先搜索&#xff09;&#xff0c;bfs&#xff08;广度优先搜索…

鸿蒙Harmony应用开发—ArkTS-@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

上文所述的装饰器仅能观察到第一层的变化&#xff0c;但是在实际应用开发中&#xff0c;应用会根据开发需要&#xff0c;封装自己的数据模型。对于多层嵌套的情况&#xff0c;比如二维数组&#xff0c;或者数组项class&#xff0c;或者class的属性是class&#xff0c;他们的第二…