Java 使用JMH的简单微基准测试

Java 使用JMH的简单微基准测试,java,microbenchmark,jmh,Java,Microbenchmark,Jmh,受此启发,我编写了一个微型基准来检查,什么更有效: 有条件地检查零除数或 捕获和处理算术异常 下面是我的代码: @State(Scope.Thread) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public class MyBenchmark { private int a = 10; // a little bit less obvious than int b = 0;

受此启发,我编写了一个微型基准来检查,什么更有效:

  • 有条件地检查零除数或
  • 捕获和处理
    算术异常
下面是我的代码:

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {

    private int a = 10;
    // a little bit less obvious than int b = 0;
    private int b = (int) Math.floor(Math.random());

    @Benchmark
    public float conditional() {
        if (b == 0) {
            return 0;
        } else {
            return a / b;
        }
    }

    @Benchmark
    public float exceptional() {
        try {
            return a / b;
        } catch (ArithmeticException aex) {
            return 0;
        }
    }
}
我对JMH完全陌生,不确定代码是否正确

我的基准正确吗?你看到什么错误了吗


旁白:请不要建议询问。对于Codereview,代码必须已按预期工作。我不确定这个基准是否能按预期工作。

我发现缺少的一点是任何一种随机性。这将使分支预测更容易完成其工作,这将使这两种方法的速度都快于实际中除以0的速度

我会对每种方法进行三种变化:

  • 使用零混合的随机数组,并使用该数组中的索引对基准进行参数化
  • 使用非零数的随机数组
  • 所有的0
  • 这将使您对总体性能有一个很好的了解,包括分支预测。对于第(1)点,使用0与非0的比率可能也很有趣

    我忘了JMH是否允许直接对数组的各个值进行参数化。如果是的话,我会用它。否则,必须对该数组的索引进行参数化。在这种情况下,我还将把all-0放在一个数组中,以便保持访问是所有测试的一部分。我还可能创建一个“控件”,它只访问数组并返回其值,这样您就可以更直接地发现开销


    还有一个小问题:我认为不需要返回浮点数,因为它们只是从除法实际产生的整数转换而来。

    关于参数化,我想,正确的方法是使用
    int
    参数确定百分比,相应地填充数组并在设置中洗牌。在基准测试中,我要么在数组上循环,要么在每一步上计算
    index=(index+1)&array.length-1
    (使用两个数组长度的幂)。你可以把落差点2和3放在一起,它们是特例。@maaartinus,这可能是一个很好的简化。不过,最后我检查了一下,JMH强烈建议不要在基准测试方法中循环。我对其中的微妙之处并不乐观,我知道;这就是我提出替代方案的原因。然而,我想,这比循环的开销要高(尽管我希望边界检查现在已经消失了(见底部)。