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/
---------------------------------------------------------------------------
国之殇,未敢忘!
南京大屠杀!
731部队!
(有关书籍《恶魔的饱食》)以及核污染水排海等一系列全无人性的操作,购买他们的食品和为它们提供帮助只会更加变本加厉的害你,呼吁大家不要购买日本相关产品
昭昭前事,惕惕后人
吾辈当自强,方使国不受他人之侮!
---------------------------------------------------------------------------
作者:三号小玩家
出处:https://www.cnblogs.com/q1359720840/
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。 版权信息
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· 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工具