JMH @Fork的目的是什么?

问题描述 投票:17回答:3

如果IIUC的每个fork创建一个单独的虚拟机,原因是每个虚拟机实例在JIT指令中可能会有细微的差异运行?

我也很好奇以下注释中的时间属性:

@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)

TIA,OLE

java benchmarking jmh
3个回答
21
投票

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

现实是,许多事情可能合谋使您的结果以一种或另一种方式倾斜,并且多次运行任何基准以建立运行差异是JMH支持的重要做法(而且大多数手动框架都无济于事。与)。运行差异的原因可能包括(但我确定还有更多原因):

  • CPU从某个C状态开始,在负载时放大频率,然后过热并缩小频率。您可以在某些操作系统上控制此问题。

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

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

至少使用几个分支来运行基准将有助于消除这些差异,并让您对基准中看到的运行方差的运行产生一个想法。我建议您从默认值10开始,然后根据您的基准通过实验将其减少(或增加)。


11
投票

JVM通过创建应用程序行为的配置文件来优化应用程序。将创建派生叉以重置此配置文件。否则,运行:

benchmarkFoo();
benchmarkBar();

可能导致测量结果与之不同

benchmarkBar();
benchmarkFoo();

因为第一个基准的配置文件会影响第二个基准。

时间决定了JMH用于预热或运行基准测试的时间长短。如果这些时间太短,则可能无法充分预热您的VM,或者您的结果可能具有太高的标准偏差。


0
投票

更新:

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在进入实时基准测试之前先运行三个热身叉和丢弃结果

© www.soinside.com 2019 - 2024. All rights reserved.