JMH @Fork的目的是什么?

Ole*_*Ole 15 java benchmarking jmh

如果IIUC每个fork创建一个单独的虚拟机,原因是每个虚拟机实例可能在JIT指令中略有不同的情况下运行?

我也很好奇时间属性在下面的注释中做了什么:

@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
Run Code Online (Sandbox Code Playgroud)

TIA,Ole

Nit*_*art 19

JMH提供fork功能有几个原因.一个是上面Rafael讨论的编译配置文件分离.但是这种行为不受@Forks注释的控制(除非你选择0分叉,这意味着没有子进程分叉来运行基准测试).您可以选择通过使用预热模式控件(-wm)运行所有基准测试作为基准热身的一部分(从而为JIT创建混合配置文件).

实际情况是,很多事情可能会以某种方式倾斜您的结果并多次运行任何基准测试来建立运行间差异是JMH支持的一个重要实践(并且大多数手动框架都没有帮助) .运行差异的原因可能包括(但我确定还有更多):

  • CPU在某个C状态下启动并在负载面上放大频率,然后过热并将其缩小.您可以在某些操作系统上控制此问题.

  • 进程的内存对齐可能导致分页行为差异.

  • 背景应用活动.
  • 操作系统的CPU分配会有所不同,导致每次运行使用不同的CPU集.
  • 页面缓存内容和交换
  • JIT编译是同时触发的,可能会导致不同的结果(当大量代码正在测试时,这种情况会发生).请注意,小型单线程基准测试通常不会出现此问题.
  • GC行为可以在不同的运行时间内触发,从而导致不同的结果.

使用至少一些分支运行基准测试将有助于消除这些差异,并让您了解在基准测试中看到的运行差异.我建议您从默认值10开始,然后根据您的基准测试将其缩减(或增加).


Raf*_*ter 10

JVM通过创建应用程序行为的配置文件来优化应用程序.创建fork以重置此配置文件.否则,运行:

benchmarkFoo();
benchmarkBar();
Run Code Online (Sandbox Code Playgroud)

可能导致不同的测量结果

benchmarkBar();
benchmarkFoo();
Run Code Online (Sandbox Code Playgroud)

因为第一个基准的轮廓影响第二个.

时间决定了JMH用于升温或运行基准的支出的长度.如果这些时间缩短,您的VM可能不会充分预热,或者您的结果可能具有过高的标准偏差.