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