性能优化-JMH

JMH(基准测试)

JMH只适合细粒度的方法测试

  • maven依赖
 <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>
  • 基本代码
package jmhTest;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.profile.GCProfiler;
import org.openjdk.jmh.profile.StackProfiler;
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;
import java.util.concurrent.atomic.AtomicInteger;


//基准测试类型,tps,avg等
@BenchmarkMode({Mode.Throughput})
//基准测试结果的时间类型
@OutputTimeUnit(TimeUnit.SECONDS)
//预热的迭代次数
@Warmup(iterations = 2,time = 2)
//几个线程
@Threads(2)
//该状态为变量是每个线程独享
@State(Scope.Thread)
//度量:iterations进行测试的轮次,time每轮进行的时长,timeUnit时长单位,batchSize批次数量(batchSize结合SingleShotTime)
@Measurement(iterations = 2,time = 2)
//几个jvm虚拟机 防止环境干扰(JVM因为使用了profile-guided optimization而“臭名昭著”,这对于微基准测试来说十分不友好,因为不同测试方法的profile混杂在一起,“互相伤害”彼此的测试结果)
@Fork(2)
public class JmhTest3 {

    public AtomicInteger atomicInteger = new AtomicInteger();

    //初始化操作
    @Setup
    public void init(){
        atomicInteger.set(0);

    }

    @Benchmark
    public void test() throws Exception{
      Thread.sleep(100);
        atomicInteger.incrementAndGet();
    }

    //销毁操作
    @TearDown
    public void destory(){
        System.out.println("==========");
        System.out.println(atomicInteger.get());
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JmhTest3.class.getSimpleName())
                //addProfiler可以输出对应的profile信息比如下
                //jmhTest.JmhTest3.test:·gc.alloc.rate       thrpt    4          0.603 ±        0.145  MB/sec
                //jmhTest.JmhTest3.test:·gc.alloc.rate.norm  thrpt    4          0.003 ±        0.001    B/op
                .addProfiler(StackProfiler.class)
                .addProfiler(GCProfiler.class)
                .build();
        new Runner(opt).run();

      }
    }
  • 其他注解
@Param
@CompilerControl //解释器的行为(方法内联\方法不内联\解释执行)
@Group //方法注解,可以把多个benchmark 定义为同一个group,则它们会被同时执行,譬如用来模拟生产者-消费者读写速度不一致情况下的表现
//todo
  • 注意事项

死码消除
常量折叠与常量传播
不要Benchmark代码里面写循环
使用 Fork 隔离多个测试方法
方法内联
伪共享与缓存行
分支预测
多线程测试(电源管理\操作系统调度和分时调用模型)
JMH测试陷阱
JAVA 拾遗 — CPU Cache 与缓存行

转载请注明:这不是一只猫的博客 » 点击阅读原文

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦