gpt4 book ai didi

java - JMH 基准测试避免 jvm 优化

转载 作者:行者123 更新时间:2023-12-04 07:50:48 24 4
gpt4 key购买 nike

我正在尝试编写 jmh 基准测试。
我遇到了各种博客,提到了 jmh 基准测试中的陷阱。常见的例子是

  • 此代码
  • int sum() {
    int a =7;
    int b = 8;
    return a+b;
    }
    将优化为
    int sum() {
    return 15;
    }
  • 此代码
  • int sum(int y) {
    int x = new Object();
    return y;
    }
    将优化为
    int sum(int y) {
    return y;
    }
    即删除未使用的对象初始化。
    但是这个列表并没有涵盖所有类型的优化 jvm 将做什么。
    下面是我面临的问题。
    让我们说有几个方法,这是调用图的样子
    int methodA(CustomObjectA a) {
    //do something
    methodB(a);
    //do something
    return returnValueA;
    }

    int methodB(CustomObjectA a) {
    //do something
    methodC(a);
    //do something
    return returnValueB;
    }

    int methodC(CustomObjectA a) {
    //do something
    return returnValueC;
    }

    我们将尝试对 methodA 进行基准测试。通过传递在状态对象中创建的 CustomObjectA。但
  • 从 JVM 的角度来看,methodC 总是使用相同的引用调用,它不会优化 methodC 以始终返回相同的 returnValueC 吗?
  • 为什么不这样做呢?
  • 我们如何确保不会进行这种优化?通过每次使用@State(Scope.Thread) 传递不同的引用?
  • 是否有任何详尽的列表来解释所有可能的优化?
  • 最佳答案

    你是说要测试methodA所有其他方法都是 private这就是调用链的样子?如果是这样,JMH这里无关紧要 - 将应用哪些优化,仍将应用于该代码。也很难说最终会发生什么优化,因为它们在 JVM 上很多。 ,还取决于许多其他因素,如操作系统、CPU 等;因此,根本不可能存在“广泛列表”。
    取决于你在那做什么 //do something例如,在每种方法中,可以省略或不省略该代码。看看这个简化的例子:

    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.NANOSECONDS)
    @Warmup(iterations = 5, time = 5)
    @Measurement(iterations = 5, time = 5)
    public class Sample {

    private static final int ME = 1;

    public static void main(String[] args) throws Exception {
    Options opt = new OptionsBuilder()
    .include(Sample.class.getSimpleName())
    .build();

    new Runner(opt).run();
    }

    @Benchmark
    public int methodOne(CustomObjectA a) {
    simulateWork();
    return 42;
    }

    @Benchmark
    public int methodTwo(CustomObjectA a, Blackhole bh) {
    bh.consume(simulateWork());
    return 42;
    }

    @State(Scope.Thread)
    public static class CustomObjectA {

    }

    private static double simulateWork() {
    return ME << 1;
    }

    }
    不同之处在于方法 methodTwo ,我用了一个所谓的 Blackhole (阅读 this 了解更多详情),而在 methodOne , 我不。结果 simulateWork已从 methodOne 中删除,如结果所示:
    Benchmark         Mode  Cnt  Score   Error  Units
    Sample.methodOne avgt 25 1.950 ± 0.078 ns/op
    Sample.methodTwo avgt 25 3.955 ± 0.120 ns/op
    另一方面,如果我稍微更改代码以具有最小可能的副作用:
    @BenchmarkMode(Mode.AverageTime)
    @OutputTimeUnit(TimeUnit.NANOSECONDS)
    @Warmup(iterations = 5, time = 5)
    @Measurement(iterations = 5, time = 5)
    public class Sample {

    public static void main(String[] args) throws Exception {
    Options opt = new OptionsBuilder()
    .include(Sample.class.getSimpleName())
    .build();

    new Runner(opt).run();
    }

    @Benchmark
    public int methodOne(CustomObjectA a) {
    simulateWorkWithA(a);
    return 42;
    }

    @Benchmark
    public int methodTwo(CustomObjectA a) {
    return simulateWorkWithA(a) + 42;
    }

    @Benchmark
    public int methodThree(CustomObjectA a, Blackhole bh) {
    bh.consume(simulateWorkWithA(a));
    return 42;
    }

    @State(Scope.Thread)
    public static class CustomObjectA {
    int x = 0;
    }

    private static int simulateWorkWithA(CustomObjectA a) {
    return a.x = a.x + 1;
    }

    }
    消除 simulateWorkWithA(a)methodOne不会发生:
    Benchmark           Mode  Cnt  Score   Error  Units
    Sample.methodOne avgt 25 2.267 ± 0.198 ns/op
    Sample.methodThree avgt 25 3.711 ± 0.131 ns/op
    Sample.methodTwo avgt 25 2.325 ± 0.008 ns/op
    请注意, methodOne 之间几乎没有区别。和 methodTwo .

    关于java - JMH 基准测试避免 jvm 优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66989430/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com