JMH-Java微基准线束

一 工具简介

官方定义:JMH is a Java harness for building, running, and analysing nano/micro/milli/macro benchmarks written in Java and other languages targeting the JVM

JMH 主要是基于方法层面的基准测试,作为rd的我们使用它,可以评估自己代码的性能。

 

二 适用场景

1、技术插件选型:使用JMH测试具备相同功能的插件,从Throughput、Average Time等维度评估

2、热点方法优化:对热点方法进行优化,可使用JMH对比测试,不断迭代优化

 

 

三 操作手册

3.1 基础概念

  • Iteration - iteration 是 JMH 进行测试的最小单位,包含一组 invocations。
  • Invocation - 一次 benchmark 方法调用。
  • Operation - benchmark 方法中,被测量操作的执行。如果被测试的操作在 benchmark 方法中循环执行,可以使用@OperationsPerInvocation表明循环次数,使测试结果为单次 operation 的性能。
  • Warmup - 在实际进行 benchmark 前先进行预热。因为某个函数被调用多次之后,JIT 会对其进行编译,通过预热可以使测量结果更加接近真实情况。

 

3.2 常用注解

序号
注解
用法
说明
 
1

@BenchmarkMode

1、配置 Mode 选项,可用于类(接口/枚举)或者方法上,可被继承

2、这个注解的 value 是一个数组,可以把几种 Mode 集合在一起执行。

如@BenchmarkMode({Mode.SampleTime, Mode.AverageTime})

3、参数配置可以被runtime options覆盖

Throughput-吞吐量,每秒执行了多少次方法,单位是ops/time

AverageTime-平均响应时间(耗时),单位是time/op

SampleTime-对所有的操作时间采样时间

SingleShotTime-单次运行获取测量时间,一般用于测试冷起的耗时,建议把Warmup 次数设为 0(即无需预热)

All-以上4中方式均执行一遍

 
2

@Benchmark

加在方法上,标注该方法可以进行基准测试 标注的方法必须被public修饰  
3

@Warmup

1、可以用在类(接口/枚举)或方法上,可被继承

2、配置预热需要的基本参数

3、参数配置可以被runtime options覆盖

为什么要预热?JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译为机器码,从而提高执行速度,为了让 benchmark 的结果更加接近真实情况就需要进行预热

iterations-预热迭代次数,默认-1

time-每次预热时间,默认-1

timeUnit-预热时间单位,默认second

batchSize-每次批量执行基准方法的个数,默认-1

 
4

@Threads

1、可以用在类(接口/枚举)或方法上,可被继承

2、参数配置可以被runtime options覆盖

每个测试进程中,用于测试的最大线程数

MAX-初始值-1,取值来源是Runtime.getRuntime().availableProcessors()

 
5

@State

1、用在类(接口/枚举)上,可被继承

2、定义state object在不同工作线程之间共享的范围

state object通常作为参数注入到benchmark方法上,也可以注入到@Setup 和@TearDown 里.

Scope.Benchmark-相同类型的实例在所有的work线程之间共享
Scope.Group-同一组内的work线程共享相同类型的实例,每个线程组有自己的state object
Scope.Thread-每个线程私有state object
 
6

@Setup

1、只能用在方法上,不可继承

2、在Benchmark标注的方法执行前运行,做数据初始化

该注解只能在@state使用的类(接口/枚举)里配合使用

Level.Trail-在每次基准运行前执行该方法
Level.Iteration-在基准每次循环前执行该方法
Level.Invocation-在每个基准方法执行前执行
 
7

@TearDown

1、只能用在方法上,不可继承

2、在Benchmark标注的方法执行后运行

该注解只能在@state使用的类(接口/枚举)里配合使用

Level.Trail-在每次基准运行后执行该方法
Level.Iteration-在基准每次循环后执行该方法
Level.Invocation-在每个基准方法执行后执行
 
8 @Timeout

1、可以用在类(接口/枚举)或方法上,可被继承

加在方法上,仅对测试类的单一方法生效。

加在类上,对测试类内部所有@Benchmark方法生效

默认单位是seconds  
9 @Param

1、只可以用在属性声明上,可以被继承

该注解用来标识在基准测试中可以配置化的参数,适合用来测试一个函数在不同的参数输入的情况下的性能

1、字段不能被final修饰且类上使用了@state修饰

2、可以用在string、枚举、基本数据类型及其包装类。取值已字符串形式给出

举例:

@param("1","3","5")

private Integer num;

3、当基准测试运行需要多个@Param时,JMH将计算运行中所有参数的外积

 
10 @OutputTimeUnit

1、可以用在类(接口/枚举)或方法上,可被继承

2、用在方法上仅对该方法生效;用在类上对类内所有方法生效

3、参数配置可以被runtime options覆盖

配置报告结果的默认时间单位  
11 @OperationsPerInvocation

todo 待补充    
12

@GroupThreads

1、只用在方法上,可以被继承

定义同一组内有多少个线程运行在被注释的方法上

默认值为1  
13

@Measurement

1、可以用在类(接口/枚举)或方法上,可被继承

2、实际基测使用的参数

3、参数配置可以被runtime options覆盖

跟@Warmup类似

iterations-预热迭代次数,默认-1

time-每次预热时间,默认-1

timeUnit-预热时间单位,默认second

batchSize-每次批量执行基准方法的个数,默认-1

 
14        

 

3.3 idea 使用

 

 

3.4 使用注意点

 

四 引用

github地址:https://github.com/openjdk/jmh

openjdk地址:http://openjdk.java.net/projects/code-tools/jmh/

https://www.cnkirito.moe/java-jmh/

 

posted @   三号小玩家  阅读(125)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
Title
三号小玩家的 Mail: 17612457115@163.com, 联系QQ: 1359720840 微信: QQ1359720840

喜欢请打赏

扫描二维码打赏

支付宝打赏

点击右上角即可分享
微信分享提示