2010-03-08 151 views
16

如何测量用Java编写的代码的速度?如何测量用Java编写的代码的速度? (AI算法)

我计划开发软件,它将使用目前所有可用的AI和ML算法来解决Sudoku,并将时间与简单的强力方法进行比较。我需要测量每种算法的时间,我想问一下这样做的最佳方法是什么?非常重要的是,无论CPU电源/内存如何,程序都必须在任何机器上有用。

谢谢。

+1

与主要问题无关,但可能有兴趣,因为您计划编写软件来解决数独。看看Norvig的解决方案。 http://norvig.com/sudoku.html – hashable 2010-03-15 06:59:07

+0

+1谢谢,是的,我知道这个解决方案 - 好东西 – 2010-03-15 20:01:23

回答

19

至于建议由别人,System.currentTimeMillis()是相当不错的,但要注意以下注意事项:

  • System.currentTimeMillis()措施经过物理时间(“挂钟时间”),而不是CPU时间。如果机器上正在运行其他应用程序,您的代码将会减少CPU,并且速度会降低。所以,只在其他空闲系统上进行测试。
  • 同样,多核系统上的多线程应用程序可能会获得额外的隐藏CPU。已用时间度量不能捕获多线程应用程序的全部复杂性。
  • Java需要一点“热身”。 VM将首先解释代码(这很慢),并且,如果给定的方法被使用了太多时间,那么JIT编译器会将该方法转换为本地代码。只有在这一点上,该方法才能达到最高速度。我建议您在致电System.currentTimeMillis()之前执行一些“空循环”。
  • System.currentTimeMillis()的准确性很少有1ms。在许多系统中,精度不会超过10毫秒,甚至更高。另外,JVM有时会运行GC,导致明显的暂停。我建议你在循环中组织你的测量并坚持至少运行几秒钟。

我们得到以下代码:

for (int i = 0; i < 10; i ++) { 
    runMethod(); 
} 
int count = 10; 
for (;;) { 
    long begin = System.currentTimeMillis(); 
    for (int i = 0; i < count; i ++) 
     runMethod(); 
    long end = System.currentTimeMillis(); 
    if ((end - begin) < 10000) { 
     count *= 2; 
     continue; 
    } 
    reportElapsedTime((double)(end - begin)/count); 
} 

正如你看到的,有前十位 “空” 运行。然后程序在一个循环中运行该方法,并根据需要多次循环,至少需要十秒。十秒钟应该足以平滑GC运行和其他系统不准确性。当我使用散列函数实现时,我使用了两秒钟,即使函数本身根本没有触发内存分配,我仍然可以获得高达3%的变化。

+2

Execellent answer – whiskeysierra 2010-03-08 20:15:06

+0

@Thomas Pornin - 非常好的详细总结,谢谢+1 – 2010-03-08 22:51:53

12

我通常使用

System.currentTimeMillis() 

来计算的时间差:即根据不同的操作系统上使用funcion的精度可能会大于1毫秒

long start = System.currentTimeMillis(); 
/* do your algorithm iteration */ 
long elapsed = System.currentTimeMillis() - start; 

精神(也十分之一msecs),所以你必须调整它对你的分析有用。

编辑:也有做与System.nanoTime()做同样的事情的替代方案,但你没有任何保证精度将纳秒。

+0

谢谢杰克,好东西+1 – 2010-03-08 19:18:17

5

这是另一种方式(与纳秒)

long nanos = System.nanoTime(); 
// execute your stuff 
long duration = System.nanoTime() - nanos; 
int seconds = (int) (duration/1000000000); 
int milliseconds = (int) (duration/1000000) % 1000; 
int nanoseconds = (int) (duration % 1000000); 
System.out.printf("%d seconds, %d milliseconds en %d nanoseconds\n", seconds, milliseconds, nanoseconds); 

毫微秒是多余的,但不错。

+2

在“大多数”机器上,纳米毫无意义。 – 2010-03-08 20:19:44

4

如果您对测量有很多精度感兴趣,则应测量CPU时间,而不是“挂钟时间”。这样你就不会测量操作系统花费其他东西的时间。为了测量这个时间,你可以看看Java benchmarking CPU time

4

虽然这里所有的答案都是有效的,但我会建议测量实时可能不是完全相关于你的目标,即比较和对比不同的搜索算法找到“最好”的。在这种情况下,计算您搜索的节点的数量要简单得多。虽然知道运行时间也很好,但是由于每种算法都可能以特定方式触及CPU /缓存/内存/磁盘,因此存在大量噪音。通过测量节点,您可以查看衡量搜索算法效果的最重要指标,因为它搜索的节点越少,查找答案的速度越快。