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】
66 0
103.【Java Microbenchmark Harness】(六)
|
Java
103.【Java Microbenchmark Harness】(三)
103.【Java Microbenchmark Harness】
58 0
103.【Java Microbenchmark Harness】(三)
|
Java
103.【Java Microbenchmark Harness】(五)
103.【Java Microbenchmark Harness】
136 0
|
Java 编译器 BI
103.【Java Microbenchmark Harness】(四)
103.【Java Microbenchmark Harness】
81 0
|
Java 测试技术
103.【Java Microbenchmark Harness】(一)
103.【Java Microbenchmark Harness】
77 0
|
Java 测试技术
在java中使用JMH(Java Microbenchmark Harness)做性能测试
在java中使用JMH(Java Microbenchmark Harness)做性能测试
|
4天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
42 17
|
14天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
16天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
16天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
下一篇
开通oss服务