如果IIUC每个fork创建一个单独的虚拟机,原因是每个虚拟机实例可能在JIT指令中略有不同的情况下运行?
我也很好奇时间属性在下面的注释中做了什么:
@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
TIA, 奥莱
答案 0 :(得分:17)
JMH提供fork功能有几个原因。一个是上面Rafael讨论的编译配置文件分离。但是这种行为不受@Forks注释的控制(除非你选择0分叉,这意味着没有子进程分叉来运行基准测试)。您可以选择通过使用预热模式控件(-wm)来运行所有基准测试作为基准热身的一部分(从而为JIT创建混合配置文件)。
现实情况是,很多事情都可以合谋倾斜你的结果,多次运行任何基准测试来建立逐次运行的差异是JMH支持的一个重要做法(并且大多数手工框架都没有帮助)。运行差异的原因可能包括(但我确定还有更多):
CPU在某个C状态下启动并在负载面上放大频率,然后过热并将其缩小。您可以在某些操作系统上控制此问题。
进程的内存对齐可能会导致分页行为差异。
使用至少一些分支运行您的基准测试将有助于消除这些差异,并让您了解在基准测试中看到的运行差异。我建议您从默认值10开始,然后根据您的基准测试将其减去(或增加)。
答案 1 :(得分:8)
JVM通过创建应用程序行为的配置文件来优化应用程序。创建fork以重置此配置文件。否则,运行:
benchmarkFoo();
benchmarkBar();
可能导致与
不同的测量结果benchmarkBar();
benchmarkFoo();
因为第一个基准的轮廓影响了第二个基准。
时间决定了JMH用于升温或运行基准的支出的长度。如果这些时间缩短,您的VM可能无法充分预热,或者您的结果可能具有过高的标准偏差。
答案 2 :(得分:2)
更新:
JMH(Java Microbenchmark线束)已添加到JDK 从JDK 12开始。
@Fork
批注,指示将如何执行基准测试value
参数控制基准测试将执行多少次,而warmup
参数控制基准测试将空试多少次在收集结果之前。
示例:
@Benchmark
@Fork(value = 1, warmups = 3)
@BenchmarkMode(Mode.AverageTime)
public void myMethod() {
// Do nothing
}
这会指示 JMH 在运行实时基准测试之前,先运行三个热身叉并舍弃结果。