103.【Java Microbenchmark Harness】(二)

简介: 103.【Java Microbenchmark Harness】

3.@State (状态)【类】

源码

@State(Scope.Thread) //各个线程独自占有一个对象
@State(Scope.Benchmark)  //整个测试总共用这一个对象
package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.*;
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;
/**
 *   @State(Scope.XXXX) 描述了这个类对象的作用域
 *   测试共享与独享的区别
 */
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_03_States {
    // 所有测试线程各用各的 (独享)
    @State(Scope.Thread) //各个线程独自占有一个对象
    public static class ThreadState {  //在我们执行Benchmark的时候,他会生成一个ThreadState对象。可以被Benchmark直接使用的,也就是入参。
        volatile double x = Math.PI;
    }
    // 根据main方法,会启动4个线程去一起执行
    @Benchmark
    public void measureUnshared(ThreadState state) {  //每一个线程的入参都是不同的对象
        state.x++;
    }
    // 所有测试共享一个实列,用于测试有状态实列在多线程共享下的性能
    // 一般用来测试多线程竞争下的性能
    @State(Scope.Benchmark)  //整个测试总共用这一个对象
    public static class BenchmarkState {
        volatile double x = Math.PI;
    }
    @Benchmark
    public void measureShared(BenchmarkState state) {  //这个依然启动4个进程,但是入参都是同一个实列,竞争非常激烈
        state.x++;
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_03_States.class.getSimpleName())
                .threads(4)   //在执行Benchmark的时候会启动4个线程
                .forks(1)
                .build();
        new Runner(opt).run();
    }
}

4.DefaultState (默认状态)【类】

源码

@State(Scope.Thread)  //放在整体类上
package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.*;
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;
@State(Scope.Thread)  //我们标记这个类会成为一个对象由JMH进行管理。多个线程会创建多个下面类对象
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_04_DefaultState {
    double x = Math.PI;
    // 我们使用默认静态类的主要目的是:  我们不用特地的去写一个静态内部类去声明一个入参。如果没有上面的注解那么我们就需要声明一个静态内部类
    @Benchmark
    public void measure() {
        x++;
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_04_DefaultState.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(opt).run();
    }
}

5.@Setup和@TearDown (初始化和销毁)【方法】

启动之前准备工作

// 启动Benchmark之前的准备工作
    @Setup // 必须在@State下的类中才能使用,实际上也算是@state管理对象的生命周期一部分

结束之后检查工作

// Benchmark结束之后的检查工作
    @TearDown  //必须在@State下的类中才能使用

源码

package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.*;
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;
/**
 *   控制state 对象中的方法在什么时候执行
 *
 *   @Setup state中的方法如何被执行
 *   @TearDown state中的方法如何执行
 *   level.Trial 默认的执行策略,整个基准测试执行一次
 */
@State(Scope.Thread)  //生命默认静态类,我们可以不用进行手动传入参数
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_05_StateFixtures {
    double x;
    // 启动Benchmark之前的准备工作
    @Setup // 必须在@State下的类中才能使用,实际上也算是@state管理对象的生命周期一部分
    public void prepare() {
        x = Math.PI;
        System.out.println("--------------1");
    }
    // Benchmark结束之后的检查工作
    @TearDown  //必须在@State下的类中才能使用
    public void check() {
        System.out.println("--------------2");
        // 这里使用了断言
        assert x > Math.PI : "Nothing changed?";
    }
    @Benchmark
    public void measureRight() {  //正确代码,正常执行
        x++;
    }
    @Benchmark
    public void measureWrong() {  // 这里是错误代码实列,会在Benchmark执行完毕后报错
        double x = 0;
        x++;
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_05_StateFixtures.class.getSimpleName())
                .forks(1)
                .jvmArgs("-ea")  //开启断言检测: assertion在一般情况下是关闭的,通过 java -ea 可以打开改功能,关闭为 -da
                .build();
        new Runner(opt).run();
    }
}

6.FixtureLevel (初始化和销毁等级)【方法】

源码

@Setup(Level.Trial)  // 与TearDown同理.启动之前会执行一次
   @TearDown(Level.Trial)  // 整个完整的基准测试之后才会执行一次
   @TearDown(Level.Iteration)  // 每轮循环完成之后才会执行一次
   @TearDown(Level.Invocation)  // 每次方法被调用都会执行一次
package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.*;
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;
@State(Scope.Thread)  //可以免除静态内部类
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 3,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_06_FixtureLevel {
    double x;
//    @Setup(Level.Trial)  // 与TearDown同理.启动之前会执行一次
//    @TearDown(Level.Trial)  // 整个完整的基准测试之后才会执行一次
//    @TearDown(Level.Iteration)  // 每轮循环完成之后才会执行一次
//     @TearDown(Level.Invocation)  // 每次方法被调用都会执行一次
    @TearDown(Level.Iteration)  // 每次方法被调用都会执行一次
    public void check() {
        System.out.println("----------1");
        assert x > Math.PI : "Nothing changed?";
    }
    @Benchmark
    public void measureRight() {
        x++;
    }
    @Benchmark
    public void measureWrong() {
        double x = 0;
        x++;
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_06_FixtureLevel.class.getSimpleName())
                .forks(1)
                .jvmArgs("-ea")
                .shouldFailOnError(false) //  默认是false,即使assert错误也不会让整个测试失败
                .build();
        new Runner(opt).run();
    }
}

相关文章
|
JSON 数据可视化 Java
103.【Java Microbenchmark Harness】(六)
103.【Java Microbenchmark Harness】
57 0
103.【Java Microbenchmark Harness】(六)
|
Java
103.【Java Microbenchmark Harness】(三)
103.【Java Microbenchmark Harness】
48 0
103.【Java Microbenchmark Harness】(三)
|
Java
103.【Java Microbenchmark Harness】(五)
103.【Java Microbenchmark Harness】
121 0
|
Java 编译器 BI
103.【Java Microbenchmark Harness】(四)
103.【Java Microbenchmark Harness】
76 0
|
Java 测试技术
103.【Java Microbenchmark Harness】(一)
103.【Java Microbenchmark Harness】
69 0
|
Java 测试技术
在java中使用JMH(Java Microbenchmark Harness)做性能测试
在java中使用JMH(Java Microbenchmark Harness)做性能测试
|
11天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
88 38
|
8天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
3天前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
4天前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
19 4