压测 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教程

    JMH应用

 

二. JMeter

  1. 比较

  A. JMH更多的是发现某块性能糟糕代码,然后对优化方案进行基准测试对比,如:JSON序列化、Bean拷贝性能;

  B. JMeter更多的是对Rest Api进行压测。

 

posted @ 2021-01-07 19:53  如幻行云  阅读(781)  评论(0编辑  收藏  举报