压测 JMH/JMeter
一. JMH
1. Maven依赖
<!-- Java性能测试 --> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>1.27</version> </dependency> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>1.27</version> <scope>test</scope> </dependency>
2. 注解
A. @BenchmarkMode/@Mode:用来配置Mode选项,作用在类或方法上,分四种模式
Throughput:整体吞吐量,每秒执行了多少次调用;
AverageTime:调用的平均时间,每次调用消耗的平均时间;
SampleTime:随机取样,最后输出取样结果的分布;
SingleShotTime:只运行一次,往往同时把Warmup次数设为 0,用于测试冷启动时的性能;
All:四种模式都执行一次;
B. @Warmup:预热所需要配置的一些基本参数,可用于类或者方法上,需要预热是因为JVM的JIT机制的存在,如果某个函数被调用多次之后,JVM会尝试将其编译为机器码,从而提高执行速度,所以为了让benchmar 的结果更加接近真实情况就需要进行预热
iterations:预热的迭代次数;
time:每次预热的时间;
batchSize:批处理大小,每次操作调用几次方法;
C. @Measurement:实际调用方法所需要配置的一些基本参数,作用在类或者方法上,参数和@Warmup相同;
D. @Threads:每个进程中的测试线程,作用在类或者方法上;
E. @Fork:进行fork的次数,即几个进程,作用在类或者方法上;
F. @State:指定一个对象的作用范围;
Benchmark:所有测试线程共享一个实例,测试有状态实例在多线程共享下的性能;
Group:同一个线程在同一个group里共享实例;
Thread:每个测试线程分配一个实例,默认值;
G. @OutputTimeUnit:为统计结果的时间单位,作用在类或方法上;
H. @Param:指定某项参数的多种情况,特别适合用来测试一个函数在不同的参数输入的情况下的性能,只能作用在字段上,使用该注解必须定义@State注解;
I. @Benchmark:表示该方法是需要进行benchmark的对象,用法和JUnit的@Test
类似;
J. @Setup:用于初始化,在执行benchmark之前被执行;
K. @TearDown:用于资源回收,在所有benchmark执行结束以后执行;
3. 示例代码
package com.ruhuanxingyun.web.manage; import com.ruhuanxingyun.web.manage.model.converter.UserConverter; import com.ruhuanxingyun.web.manage.model.dto.UserDTO; import com.ruhuanxingyun.web.manage.model.vo.UserVO; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import org.openjdk.jmh.results.format.ResultFormatType; 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 org.springframework.beans.BeanUtils; import java.util.concurrent.TimeUnit; /** * @description: 对象转换性能测试类 * @author: ruphie * @date: Create in 2021/1/9 13:06 * @company: ruhuanxingyun */ @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 3, time = 2) @Measurement(iterations = 4, time = 3) @Threads(2) @Fork(1) @State(value = Scope.Benchmark) @OutputTimeUnit(TimeUnit.NANOSECONDS) public class ObjectConvertTest { private UserDTO userDTO; /** * 初始化,在执行benchmark之前被执行 */ @Setup public void setUp() { userDTO = UserDTO.builder() .id(1L) .ip("127.0.0.1") .name("ruphie") .phone("88888888888") .password("123456") .entry("pc") .mode("password") .rsaUuid("123456") .build(); } /** * BeanUtils工具类测试 * * @param blackhole blackhole */ @Benchmark public void beanUtilsConvert(Blackhole blackhole) { UserVO userVO = new UserVO(); BeanUtils.copyProperties(userDTO, userVO); blackhole.consume(userVO); } /** * MapStruct工具类测试 * * @param blackhole blackhole */ @Benchmark public void mapStructConvert(Blackhole blackhole) { UserVO userVO = UserConverter.INSTANCE.dto2Vo(userDTO); blackhole.consume(userVO); } /** * 资源回收,在所有benchmark执行结束以后执行 */ @TearDown public void tearDown() { userDTO = null; } /** * 这是benchmark启动的入口,同时包含JMH的配置 * * @param args 参数 * @throws RunnerException e */ public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder() .include(ObjectConvertTest.class.getSimpleName()) .result("web-manage/result.json") .resultFormat(ResultFormatType.JSON) .build(); new Runner(opt).run(); } }
结果对比:
4. jar包方式
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <finalName>jmh-test</finalName> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>org.openjdk.jmh.Main</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build>
5. IDEA插件
可参考:JMH教程
二. JMeter
1. 比较
A. JMH更多的是发现某块性能糟糕代码,然后对优化方案进行基准测试对比,如:JSON序列化、Bean拷贝性能;
B. JMeter更多的是对Rest Api进行压测。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗