是否可以使用 JMH 作为 Maven 验证检查?

Is it possible to use JMH as a maven validation check?

我有一段性能关键代码,我想将其作为 Maven 构建步骤进行保护,即 JMH 会 运行 并检查性能是否因本地更改而降低。

如何使用 JMH 检查此类退化?

我找到了一些相关链接:

我之前实现了自动化性能测试(尽管不是在 Java 中,也不是在 CI 环境中)。需要注意的一个关键点是,您永远不会 运行 将其作为绝对值,因为基准测试所使用的机器 运行 可能会有所不同。 BogoMips 或测试相关类型的参考可用作相对比较。然后将基准测量为该参考时间的某个倍数,具有上限和下限。

虽然您通常会担心基准测试变慢(降级),但检查上限也很重要,因为它可能表明意外加速(更好的硬件支持),这应该表明 per-system/architecture绑定需要检查

JMH Maven 插件不支持此功能。您必须编写自己的 Maven 插件来执行此操作,或者您必须在构建生命周期内使用 java exec 插件来执行测试。您可以将基准测试结果写入文件并找到另一个 Maven 插件,该插件读取文件并在不匹配给定约束时中断构建。

但是,我怀疑这是个好主意。如果您的代码更改显着改变了基准,则很可能您的基准不再适合您的代码。更糟糕的是,即使您的代码变慢了,您的基准测试也可能会变得更快,因为基准测试不再反映真实的用例。此外,您必须找到基准,因为基准不适合衡量 "absolute" 运行时间。

对于这种方法适用的地方可能存在一些特殊情况,但您应该考虑是否真的值得麻烦。

看起来有可能,这个 netty.io commit 添加了对包装在 Junit 测试中的 JMH 的支持。

我从 JMH 选项中注意到:

-rf <type>      Result format type.
                See the list of available result formats first. 
-rff <filename> Write results to given file. 

意味着我可以告诉 Benchmark 将其结果输出到一个 JSON 文件,然后我可以将其作为 Junit 运行.

的一部分进行解析

最后一部分是比较 运行 Junit 内部的其他东西,也许 SPECjvm2008 ?

我建议通过 OptionsBuilder 简单地构建一组 Runner 选项,并从 Junit 测试中对其调用 run。 虽然一些作者以不在 "clean" 环境中 运行 为基准而反对这样做,但我认为效果非常微不足道,并且在与参考 运行 进行比较时可能无关紧要同样的环境。

有关手动设置 Runner 的最简单示例,请参阅 here

Runner.run()(或在单个基准测试的情况下 Runner.runSingle())然后将 return 一个 Collection<RunResult> 或只是 RunResult,断言可以是反对。

为了做到这一点,您可以简单地使用 Statistics(参见文档 here),您可以通过 RunResult.getPrimaryResult().getStatistics()RunResult 中提取并针对数字进行断言您可以从 Statistics

中提取的值

... 或使用 isDifferent() 方法,您可以选择在置信区间内比较两个基准 运行s(可能有助于自动捕获两个方向的异常值)。