jvm 确保编译JMH基准方法

wkftcu5l  于 2022-11-07  发布在  Java
关注(0)|答案(1)|浏览(156)

我有一个用@Param控制输入大小的基准测试,例如:

@State(Scope.Benchmark)
class MyBenchmark {
  @Param({"100", "10000", "1000000"})
  public int ARRAY_SIZE;
  public int[] INPUT;

  @Setup
  public void setUp() {
    INPUT = new int[ARRAY_SIZE];
    // ...
  }

  @Benchmark
  public void compute() {
    // ...
  }

}

当输入很大时,compute的调用次数不足以在预热过程中触发编译。由于我希望测量峰值性能,因此我希望确保在预热过程中调用该方法的次数足以进行编译。
有什么好的方法可以做到这一点吗?我可以设置一个更高的预热迭代次数,但这将适用于所有的输入大小,当它真的只需要为大的,没有得到编译。

eh57zj3b

eh57zj3b1#

您可以尝试让编译更早发生,而不是增加迭代次数。
从JDK 9开始,有-XX:CompileThresholdScaling JVM选项来调整编译策略的频率和阈值。值越低,编译开始得越早。
例如,-XX:CompileThresholdScaling=0.05将使阈值降低20倍。
该选项可以全局应用,也可以基于每个方法应用。例如,要将其仅应用于compute基准,请添加以下注解:

@Benchmark
@Fork(jvmArgsAppend = {"-XX:CompileCommand=CompileThresholdScaling,*MyBenchmark*::compute*,0.05"})
public void compute() {
  // ...
}

或者,您可以将更大的参数值提取到另一个@State对象中,并使用不同的@Warmup选项创建一个单独的基准方法:

@State(Scope.Benchmark)
public static class SmallParams {
    @Param({"100", "10000"})
    int size;
}

@State(Scope.Benchmark)
public static class LargeParams {
    @Param({"1000000"})
    int size;
}

@Benchmark
@Warmup(iterations = 5)
public void computeSmall(SmallParams params) {
    //
}

@Benchmark
@Warmup(iterations = 50)
public void computeLarge(LargeParams params) {
    //
}

或者只运行基准测试两次,覆盖命令行中的参数:

-p size=100,10000 -wi 5
-p size=1000000 -wi 50

相关问题