问题标签 [jmh]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
294 浏览

eclipse - 在 Eclipse 中为 gradle 项目运行 JMH 基准测试

是否有任何直接的方法可以在 Eclipse 中为 gradle 项目运行 JMH 基准测试。我尝试过但遇到了没有运行基准的问题(然后在资源中手动复制了生成的 META-INF 女巫 Mircobenchmark 文件)

然后它给了 generated.package_name.testClass class not found 异常。将它添加到 build-path->source 会给出错误,因为它期望包名称为 gradle/classes/generated/package_name

0 投票
1 回答
28 浏览

java - 这个 forkjoinreuse 和 forkjoindeeprecursive 是什么意思?

我一直在尝试理解这个 micro-benchmark

在源代码中有四种类型的 ForkJoin:ForkJoinreuseForkJoinrecursivedeep. 我不明白它们与 and 有什么不同ForkJoinForkJoinrecursive即使我已经阅读了资料。

0 投票
2 回答
637 浏览

java - JMH:性能比较

我试图提高我的程序的性能。我用 JMH 比较了我的两个版本,但我不知道是否有真正的区别。

我的结果示例:

这些结果能否显示版本 1 和版本 2 之间的真正区别?

0 投票
2 回答
1696 浏览

java - 使用 JMH 时的奇怪输出

我正在使用 jmh 对一个简单的应用程序进行基准测试(来自 SO question Unexpected Scalability results in java fork-join ),使用 maven 并遵循http://openjdk.java.net/projects/code-tools中建议的命令行方法/jmh/。成功设置和构建基准后,我使用 avgt 模式得到以下基准结果:

我不确定如何解释这个输出,但我很确定出了什么问题......?知道什么或如何调试这个吗?

0 投票
1 回答
392 浏览

java - CPU 的 div 指令和 HotSpot 的 JIT 代码之间的性能差距很大

自从 CPU 出现以来,人们普遍认为整数除法指令很昂贵。我去看看今天有多糟糕,在拥有数十亿晶体管的 CPU 上。我发现idiv对于常量除数,硬件指令的性能仍然比 JIT 编译器能够发出的代码(不包含该idiv指令)差得多。

为了在专用的微基准测试中提出这一点,我编写了以下内容:

简而言之,我有两种在各个方面都相同的方法,除了一个 ( divVar) 执行除以从数组中读取的数字,而另一个除以编译时常量。这些是结果:

性能比是相当非凡的。我的期望是现代英特尔处理器有足够的空间,并且它的工程师有足够的兴趣在硬件中实现复杂但高性能的除法算法。然而,JIT 编译器通过向英特尔发送执行相同工作的其他一些指令流来击败英特尔,速度仅快七倍。如果有的话,专用微码应该能够比 JIT 通过汇编指令的公共 API 更好地利用 CPU。

怎么idiv还是这么慢,根本限制是什么?

想到的一个解释是除法算法的假设存在,该算法在很晚的时候第一次涉及到被除数。JIT 编译器将领先一步,因为它会在编译时评估仅涉及除数的第一部分,并仅将算法的第二部分作为运行时代码发出。这个假设是真的吗?

0 投票
2 回答
739 浏览

java-8 - 使用 paralell() 时 JMH 吞吐量值不一致

我是 JHM 的新手,为了测试它,我写了以下简单的方法

测试结果差异很大

多次运行后观察到相同的行为。在减少预热迭代后,我仍然看到在 5/6 次迭代后 ops/s 有所下降。测试套件中使用并行操作的其他基准测试执行一致。

我是 JMH 的新手,我有几个问题。

  • 我可以调整 JMH 中的任何配置参数以减少差异吗?
  • 这是所讨论方法的多次迭代的预期行为吗?
  • 如果 JHM 报告正确,我该如何调试此方法并找出 ops/s 下降的原因?

一些规格

编辑

感谢所有反馈,非常感谢。

今天早上我重新运行了基准测试,整晚都没有打开笔记本电脑。不一致的行为完全消失了。我将迭代次数提高到 1000 次,但 ops/s 仍然保持一致。

检查CPU温度它稳定在84度。

我无法重现此问题,下次我认为我的 CPU 可能过热时,我想重新运行此基准测试并监控 CPU 温度以查看此行为是否再次发生。

运行时使用确实显示了与Arrays.stream().map().sum()-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining的不稳定性能中的方法类似的编译模式,但我认为这不是这个问题的根本原因。


编辑 2

能够通过添加-XX:MaxInlineLevel=12标志来重现和解决。


-XX:MaxInlineLevel=12仍然没有找到根本原因,为什么我以前被省略时无法重现该问题。据我所见,我使用的是相同的设置。在我的笔记本电脑闲置一段时间后,我可能会再次尝试运行基准测试,但现在我很高兴我对 JIT 内联有了一些了解。

0 投票
2 回答
104 浏览

java - 奇怪的优化器行为:JVM 坚持一种优化并且不适应

我有一个漫长的过程,有两个主要阶段。第一阶段和第二阶段的执行路径略有不同。

我刚刚意识到,如果我创建具有不同名称的相同方法的副本并在每个阶段使用不同的名称,根据 JMH ( -server, on java-7-openjdk-amd64),我在第二阶段的方法调用中获得超过 25% 的加速(在 5 次调用预热后,对该方法的数百万次调用,以 5 次调用来衡量)。

有没有办法告诉 JVM 忘记以前对方法的优化并从头开始重新学习?

在下面的示例代码中,基准测试方法是,并且在调用和in 的run两个版本之间进行比较。checkCharcheckChar0stage2

0 投票
1 回答
514 浏览

java - Math.log() 的死代码消除如何在 JMH 示例中工作

每个试图利用 JMH 框架创建一些有意义的测试的人都会遇到 JMH 示例测试(http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java /org/openjdk/jmh/samples/)。当我们浏览它们时,我们被死代码消除(JMHSample_08_DeadCode.java)困住了。

摘抄:

measureWrong() 的测量值将与基线测试大致相同。因为从未使用过 Math.log() 的返回值。因此,HotSpot 编译器将消除死代码。好的,理解但是编译器如何决定可以消除 Math.log() 。

当我们仔细观察测试时,我们注意到 Math.log() 是一个本地方法。并且本机调用进入操作系统并执行相应的库。对?这导致我们假设,如果不使用它们的返回值并且它们不执行 io 操作,编译器可以消除本机调用。

我们想知道如果驻留在操作系统中某处并处理来自 java 世界的本机调用的库不提供返回值但执行 io 操作(例如日志记录)会怎样。这些指令会被彻底清除吗?

为了证明我们的假设,我们使用简单的 JMH 测试和本地调用重构了场景。我们编译了三个 c-native 库来执行:

  1. 返回 42
  2. 参数添加
  3. 空文件创建

正如我们在 JMH 测试中所称的那样(类似于 measureWrong() 测试),它们都没有被消除,即使是不执行 io 操作的那个也没有。由于测试结果无法证实我们的假设。本机调用无法优化,这意味着 Math.log() 和自定义本机调用没有相同的基础。他们不是平等的本地人。也许我们在原生 lib 代码中犯了一个错误,至少应该取消 test 1 的原生调用。如果这是真的,我们将与您分享我们的代码。

所以我们进一步搜索,发现了一个术语 Intrinsics,其中 java 代码将替换为对应于架构非常优化的代码。java.lang.Math.log() 具有这样的内在实现。Natives和Intrinsics之间有什么关系吗?如果上面关于 Natives 和 Intrinsics 之间关系的假设成立,编译器会执行以下步骤来消除 native 调用吗?

  • 在编译时,HotSpot 检查 Math.log() 的内在实现(在 jdk 中?)是否存在,并用该代码替换 Math.log()。
  • 之后第二次检查发生在 HotSpot 查看方法的返回值的地方。根据这个结果,HotSpot 决定完全消除 Math.log() 调用。
0 投票
0 回答
1041 浏览

java - 如果工作由不同的线程执行,如何使用 JMH 对吞吐量进行基准测试?

我们不确定如何对应用程序的一部分进行基准测试,其中多个线程(生产者)写入单个 ConcurrentHashMap。此外,如果达到特定大小,单个消费者线程会用空的地图切换地图。map 的切换是必要的,因为生产者线程需要尽可能快地写入 map,而不会产生额外的拥塞。消费者线程还处理地图的元素并将它们存储在缓冲区中。最后,另一个线程会将缓冲区内容发送到应用程序的其他一些组件。

我们不清楚如何测量将元素写入 ConcurrentHashMap 直到它们准备好发送(-> 聚合吞吐量)所需的时间(和相应的吞吐量)。目前,我们排除了发送元素以简化操作。我们知道吞吐量受到地图大小的限制。但是,我们希望对其进行测量以将其与未来实现的吞吐量进行比较。

到目前为止,我们调查了以下场景:

Silo-Test
该基准测试将测量单个基准测试中的每个步骤。基准 A:将元素插入 Map 直到达到大小(= batchSize)。基准 B:测量元素存储在缓冲区中需要多长时间。
优点:相对容易实现。
缺点:通过将基准 A 和 B 加在一起,会丢失线程交互性并且不会给出吞吐量聚合。

Flat-Test
与 Silo-Test 相比,所有步骤都在一个基准测试中执行(单线程)。首先将 X 元素插入 Map,然后切换 Map,处理 X 元素并将其存储到缓冲区中。
优点:相对容易实现。
缺点:线程交互性丢失,基准测试只能由一个线程(-> 只有一个生产者)运行,因为当前实现不支持同时切换映射和元素处理。

Dynamic-Amount-Test(首选测试)
基准测试方法将在每次调用时将单个元素插入到映射中。消费者线程将在@Setup 阶段启动,并在测试期间将元素传递到缓冲区。在基准测试结束时,缓冲区中收集的元素计数被提供给 JMH 用于结果计算,而不是使用基准方法的调用。我们不知道这种开箱即用的功能允许我们在基准测试结束时向 JMH 提供缓冲区大小。很可能我们需要修改 JMH 来满足这个要求(对吗?)。
优点:组合吞吐量由 JMH
缺点计算:没有开箱即用的功能,JMH 修改可能很危险(影响测量,基准有效性不清楚)

附加说明:在这种情况下,我们还必须处理非稳态基准。我们考虑过使用 JMH 的批处理可能性并使用不同的大小进行测试。

预先感谢任何建设性的回应。

0 投票
1 回答
2063 浏览

java - JMH 如何测量低于粒度值的执行时间?

因此,我尝试使用微基准测试,选择了 JMH,阅读了一些文章。JMH 如何测量低于系统计时器粒度的方法的执行?

更详细的解释:

这些是我正在运行的基准测试(方法名称不言自明):

以下是结果:

目前在 Windows 7 上运行,并且正如在各种文章中所描述的那样,它具有很大的粒度 (407 ns)。用下面的基本代码检查它确实是每 ~400ns 出现一个新的计时器值:

很难完全理解生成的方法究竟是如何工作的,但是通过反编译的 JMH 生成的代码,它似乎在执行前后使用相同的 System.nanoTime() 并测量差异。当粒度为 400 ns 时,它如何能够测量几纳秒的方法执行?