确保JMH基准方法得到编译



我有一个@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在预热期间没有被调用足够的次数来触发编译。由于我想测量峰值性能,因此我希望确保在预热期间调用该方法以进行编译。

是否有好的方法来做到这一点?我可以设置更大的预热迭代次数,但这将适用于所有输入大小,而实际上只需要对不被编译的大输入。

与其增加迭代次数,不如尝试提前编译。

从JDK 9开始,有-XX:CompileThresholdScalingJVM选项来调整编译策略的频率和阈值。值越小,编译开始越早。
-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

相关内容

  • 没有找到相关文章

最新更新