CPU在Java中的执行时间



我想计算在Java中执行我的函数需要多少CPU时间。目前我正在做如下的事情。

   long startTime = System.currentTimeMillis();
    myfunction();
    long endTime = System.currentTimeMillis();
    long searchTime = endTime - startTime;

但是我发现对于相同的I/p,我得到不同的时间取决于系统负载。

那么,如何获得执行函数所需的确切CPU时间。

  1. System.currentTimeMillis()将只测量挂钟时间,从不测量CPU时间。
  2. 如果您需要时钟时间,那么System.nanoTime()通常比currentTimeMillis()更精确(并且永远不会更差)。
  3. ThreadMXBean.getThreadCPUTime()可以帮助您了解给定线程使用了多少CPU时间。使用ManagementFactory.getThreadMXBean()来获得ThreadMXBeanThread.getId()来找到您感兴趣的线程的id。注意,这个方法不需要在每个JVM上都支持!

随着JVM的升温,所花费的时间将有所不同。第二次运行总是比第一次快。(第一次必须加载类并调用静态块)当你运行该方法10,000次后,它将再次更快(它将代码编译为本机机器码的默认阈值)

为了获得微基准测试的可再现的平均计时,我建议您忽略前10,000次迭代,然后运行2-10秒。

long start = 0;
int runs = 10000; // enough to run for 2-10 seconds.
for(int i=-10000;i<runs;i++) {
    if(i == 0) start = System.nanoTime();
    // do test
}
long time = System.nanoTime() - start;
System.out.printf("Each XXXXX took an average of %,d ns%n", time/runs);

非常重要:每个方法只执行其中一个循环。这是因为它基于如何使用它来优化整个方法。如果你有一个像这样的繁忙循环,后面的循环会显得更慢,因为它们没有运行,并且会优化得很差。

进行微基准测试的正确方法是学习并正确使用Java微基准测试工具(JMH),它由OpenJDK 12以后的JEP 230微基准套件增强。搜索"java jmh"将生成一些有用教程的链接。我喜欢Jakob Jenkov的博客文章,当然还有Aleksey Shipilëv的任何东西,他是JMH的主要开发人员和维护者。只要在提供的链接上选择他JMH演讲的最新版本即可。

Java基准测试非常重要,测试代码做的工作越少,兔子洞就越深。在试图掌握性能问题时,时间戳可能非常容易产生误导。当您尝试度量外部事件的等待时间(例如等待对HTTP请求的响应和此类事情)时,时间戳可以发挥作用,只要您能够确保在等待线程的解锁和获取"后"之间花费的时间可以忽略不计。时间戳,只要线程一开始就适当地解除阻塞。当且仅当等待时间至少为几十毫秒时,通常会出现这种情况。如果你在某事上等待,你就很好了。然而,预热和缓存效应会在任何一天发生,并破坏您的测量对实际性能的适用性。

在测量"确切的CPU时间"方面,可以采用Joachim Sauer的回答详细说明的方法。当使用JMH时,可以在外部测量CPU使用情况,然后对测量的迭代次数取平均值,然而,由于这将包括控制的开销,这种方法对于比较测量很好,但不适合派生"我的函数xy",因为在我使用的CPU架构上,平均每次迭代需要多少CPU秒。在现代CPU和JVM上,这样的观察实际上是不可能的。

有许多分析器(Jprofile、Jprobe、Yourkit)可用于分析此类数据。不仅如此,还有更多……(如内存利用率、线程细节等)

你可以在这里找到你的答案:

如何在Java中为方法的执行计时?

有很多计算方法执行时间的例子

最新更新