从 JMH 的分析中排除 @Setup 方法

Posted

技术标签:

【中文标题】从 JMH 的分析中排除 @Setup 方法【英文标题】:Exclude @Setup methods from profiling in JMH 【发布时间】:2021-04-18 10:53:09 【问题描述】:

我正在使用 JMH 对 JVM 上的一些代码进行基准测试,并且我编写了一个注释为 @Setup 方法的方法,该方法需要很长时间才能运行。当然,正如预期的那样,此方法并未包含在基准测试中 - 但不幸的是,当我尝试使用 JMH 的内置分析支持时,它 包含在内,这会污染分析报告以各种不相关在实际基准测试方法本身期间未调用的方法调用。这种行为似乎没有在任何地方记录,但在 JMH 源代码中,有以下注释:

// profilers start way before the workload starts to capture
// the edge behaviors.

在 JMH 中似乎没有任何选项可以禁用此行为。如何将@Setup 方法以及源自它们的任何堆栈跟踪排除在探查器结果中? (@Setup 方法不会直接或间接从 @Benchmark 方法调用。)

【问题讨论】:

【参考方案1】:

一个相对明显的方法是避免使用 JMH,而只使用一个分析器。但是,这需要一些设置。在 Java 中,您可以添加一个 public static void main 方法,或者在 Scala 2.12 中,您可以添加一个扩展 App 的伴侣 object,以创建一个实用程序应用程序,其中应包含以下代码:

Benchmark b = new Benchmark(); // assuming your benchmark is defined in a class called Benchmark
b.setupMethod();
System.out.println("Attach a profiler and then press Enter to continue");
new Scanner(System.in).nextLine();
b.benchmarkedMethod();

如果您正在使用采样分析器并且您的benchmarkedMethod 非常快,请将其放入具有多次迭代的for 循环中,以便程序运行足够长的时间以使采样分析器能够收集足够的样本用于有用的报告。但是,如果您使用的是尝试记录所有方法调用的传统分析器,并且您的基准测试方法在功能上是确定性的(它做同样的事情,每次都取模不同的内存地址和类似的低级事情),不要这样做那是因为它完全没有必要进行分析。

然后运行实用程序,按照提示附加分析器,然后按 Enter。

【讨论】:

以上是关于从 JMH 的分析中排除 @Setup 方法的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList去重常用的四种方式及性能对比(JMH性能分析)

jvisualvm 不会从 CPU 分析中排除某些方法

JMH参数详解

如何从 SonarQube 分析中排除目录?

JMH性能测试

JMH 在使用 perf 进行分析时给出 <not counted> 值