在对Java应用程序进行基准测试时,如何补偿没有“安静”计算机的情况?

时间:2019-04-10 04:58:24

标签: java performance benchmarking java-9

我一直都在进行数值模拟。我可以判断我的模拟是否行不通(即,它们无法给出可接受的答案),但是由于我通常在后台运行的指定内核上运行可变数量的模拟(在我工作时),因此查看时钟时间可以告诉我他们跑得有多快就比什么都没有。

我不需要时钟时间;我想要CPU时间。这些文章似乎都没有提到这个小方面。特别是,使用“安静”机器的建议似乎模糊了正在测量的内容。

我不需要太多细节,我只是想知道模拟A的运行速度比模拟B或C快或慢15%,尽管事实是A自己运行了一段时间,然后我首先是B,然后是C。也许我在退役之前玩了一段时间,这会在那段时间中运行更高优先级的应用程序。不要告诉我理想上应该使用“安静”的机器。我的问题专门询问在没有专用机器的情况下如何进行基准测试。我也不想在评估应用程序运行时间的同时降低应用程序的效率。似乎只有在需要大量细节时才需要大量开销。我对吗?

我想修改我的应用程序,以便在检查批处理作业是否成功时,还可以看到在CPU时间中达到这些结果所花费的时间。基准测试可以给我我想要的答案吗?我可以简单地使用Java 9的基准测试工具,还是需要其他工具?

1 个答案:

答案 0 :(得分:4)

在大多数操作系统上,您可以从JVM外部轻松地测量CPU时间而不是墙上时钟时间。例如time java foo.jar在Unix / Linux上,甚至perf stat java foo.jar在Linux上。

最大的问题是某些工作负载比其他工作负载具有更多的并行性。考虑这个简单的例子。这是不现实的,但是数学运算对于在更高并行和更少并行阶段之间交替的真实程序是一样的。

  • 版本A完全是连续的9分钟,并保持8个内核饱和1分钟。挂钟时间= 10分钟,CPU时间= 17分钟

  • B版本是串行的1分钟,并保持所有8个内核忙5分钟。挂墙时间= 6分钟,CPU时间= 5 * 8 +1 = 41分钟

如果仅查看CPU时间,您将不知道哪个版本停留在其工作的固有串行部分。 (这是假设纯粹是CPU约束,没有I / O等待。)

但是对于两个主要都是串行的类似实现,CPU时间和挂墙时间可以给您一个合理的猜测。

但是,像HotSpot这样的现代JVM使用多线程垃圾回收,因此即使您自己的代码从不启动多个线程,一种使GC能够完成更多工作的版本也可以使用更多的CPU时间,但速度仍然更快。但是,那可能很少见。


另一个令人困惑的因素:争用内存带宽和缓存占用空间将意味着需要更多的CPU时间来完成相同的工作,因为您的代码将花费更多的时间等待内存。

在HyperThreading或其他SMT cpu架构(如Ryzen)中,一个物理核心可以充当多个逻辑核心,两个逻辑核心都处于活动状态会以降低每个线程性能为代价提高总吞吐量。

因此,与另一个逻辑内核也处于活动状态相比,在HT兄弟处于空闲状态的内核上1分钟的CPU时间可以完成更多的工作。

在两个逻辑核心都处于活动状态的情况下,现代的Skylake或Ryzen可能会为您提供50%至99%的单线程性能,使所有执行资源可用于单个核心,这完全取决于代码运行的方式每个线程。 (如果两个FP延迟的瓶颈都通过非常长的循环携带的依赖链添加和相乘,那么乱序执行就看不到了,例如,两个都使用严格的FP来对非常大的数组求和,这是HT的最佳情况。这两个线程都不会减慢另一个线程的速度,因为FP添加吞吐量是FP添加延迟的3到8倍。)

但是在最坏的情况下,如果两个任务因L1d高速缓存未命中而减慢了很多速度,那么HT甚至可能因为一次在同一内核上运行而不是一次运行而丢失吞吐量。