103.【Java Microbenchmark Harness】(三)

简介: 103.【Java Microbenchmark Harness】

7.FixtureLevelInvocation (固定级别调用)

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.*;
@OutputTimeUnit(TimeUnit.MICROSECONDS)  // 报告时间单位
@BenchmarkMode(Mode.AverageTime)   // 输出报告
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_07_FixtureLevelInvocation {
    @State(Scope.Benchmark)   // 共享一个对象
    public static class NormalState {
        ExecutorService service;
        @Setup(Level.Trial)  // 整个基准调用之前进行准备工作 (全局一次)
        public void up() {
            System.out.println("--------准备工作");
            service = Executors.newCachedThreadPool();
        }
        @TearDown(Level.Trial)  // 整个基准结束之后进行检查工作 (全局一次)
        public void down() {
            System.out.println("------------销毁");
            service.shutdown();
        }
    }
    public static class LaggingState extends NormalState {
        public static final int SLEEP_TIME = Integer.getInteger("sleepTime", 10);
        @Setup(Level.Invocation)  //每次方法被调用都会执行
        public void lag() throws InterruptedException {
            TimeUnit.MILLISECONDS.sleep(SLEEP_TIME);  //调用的时候会睡眠10毫秒
        }
    }
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)  // 输出的方式是每次多少秒
    public double measureHot(NormalState e, final Scratch s) throws ExecutionException, InterruptedException {
        return e.service.submit(new Task(s)).get();
    }
    @Benchmark
    @BenchmarkMode(Mode.AverageTime)  //输出的方式是每次多少秒
    public double measureCold(LaggingState e, final Scratch s) throws ExecutionException, InterruptedException {
        return e.service.submit(new Task(s)).get();
    }
    @State(Scope.Thread)  // 独享下面的静态方法
    public static class Scratch {
        private double p;
        public double doWork() {
            p = Math.log(p);
            return p;
        }
    }
    public static class Task implements Callable<Double> {
        private Scratch s;
        public Task(Scratch s) {
            this.s = s;
        }
        @Override
        public Double call() {
            return s.doWork();
        }
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_07_FixtureLevelInvocation.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(opt).run();
    }
}

8.DeadCode (JVM调优)

源码

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;
/*** 这个列子展示了一种场景: 有些代码会变成JVM优化掉,使得基准测试结果不可用。
 *
 *  baseline(): 空方法
 *
 *  measureWrong(): 由于计算结果并没有返回,JVM会自动优化,使其耗时测得与baseline()结果一样
 *
 *  measureRight(): 将计算结果返回,JVM自动优化,这样才能真实测得真实的对象
 *
 */
@State(Scope.Thread)  //静态内部可省略
@BenchmarkMode(Mode.AverageTime)  //每次多少秒
@OutputTimeUnit(TimeUnit.NANOSECONDS)  //单位
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_08_DeadCode {
    private double x = Math.PI;
    private double compute(double d) {
        for (int c = 0; c < 10; c++) {
            d = d * d / Math.PI;
        }
        return d;
    }
    @Benchmark
    public void baseline() {
        // do nothing, this is a baseline
    }
    @Benchmark
    public void measureWrong() {
        // This is wrong: result is not used and the entire computation is optimized away.
        compute(x);  //因为我们没有使用计算结果,JVM会自动把这段代码优化掉,相当于测试了一个空方法。
    }
    @Benchmark
    public double measureRight() {
        // This is correct: the result is being used.
        return compute(x);  //让JVM不能优化掉,我们返回了结果
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_08_DeadCode.class.getSimpleName())
                .forks(1)
                .jvmArgs("-server")  //注意这里一定要设置server模式,为了充分使用JVM调优。
                .build();
        new Runner(opt).run();
    }
}

9.Blackholes (黑洞拒绝JVM调优)

黑洞: 可以有效的避免过于激进的优化

源码

@Benchmark
    public void measureRight_2(Blackhole bh) {
        // 如果执行结果不使用编译器优化
        // 为了防止编译器自作主张,这里使用JMH提供的黑洞对象执行结果进行消费
        bh.consume(compute(x1));
        bh.consume(compute(x2));
    }
package org.openjdk.jmh.samples;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
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;
/**
 *  空方法会被JVM给优化掉,但黑洞可以拒绝优化
 */
@BenchmarkMode(Mode.AverageTime)  //输出方式
@OutputTimeUnit(TimeUnit.NANOSECONDS) //输出的时间
@State(Scope.Thread) //面内部静态
@Warmup(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS)  //预热次数和时间
@Measurement(iterations = 1,time = 1,timeUnit = TimeUnit.SECONDS) //测试次数和时间
public class JMHSample_09_Blackholes {
    double x1 = Math.PI;
    double x2 = Math.PI * 2;
    private double compute(double d) {
        for (int c = 0; c < 10; c++) {
            d = d * d / Math.PI;
        }
        return d;
    }
    @Benchmark
    public double baseline() {  //整一个,且真实有效的只有一个
        return compute(x1);
    }
    @Benchmark
    public double measureWrong() { //整两个,但真正有效值为1个
        compute(x1);  //编译器自动识别,直接被JVM优化掉
        return compute(x2);
    }
    @Benchmark
    public double measureRight_1() {  //整两个且真实计算的有2个
        return compute(x1) + compute(x2);
    }
    @Benchmark
    public void measureRight_2(Blackhole bh) {
        // 如果执行结果不使用编译器优化
        // 为了防止编译器自作主张,这里使用JMH提供的黑洞对象执行结果进行消费
        bh.consume(compute(x1));
        bh.consume(compute(x2));
    }
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHSample_09_Blackholes.class.getSimpleName())
                .forks(1)
                .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】
75 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服务