用Java测量时间

所以我试图测量两个不同的算法实现完成给定任务所花费的时间,结果如下:

i alg1 alg2 4 0.002 0.0 5 0.001 0.0 6 0.003 0.002 7 0.023 0.01 8 0.055 0.041 9 0.056 0.0 10 0.208 0.101 11 1.767 0.694 12 18.581 7.784 

i只是一些输入参数。

我已经使用以下(幼稚)函数测量了算法的性能:

 private double getDuration() { return (double)(System.currentTimeMillis() - startTime) / (double)1000; } 

获得更多真实结果(除了0.0,显然不是真的!)比使用System.currentTimeMillis()更好的方法是什么? 我知道我可以一遍又一遍地运行算法并总结他们的结果,但我有这种直觉,可能有一些更健壮的方法来测量Java中的传递时间(如果可能的话, realusersys !)。

谢谢

对于基本计时,您可以使用Guava的Stopwatch类 (或者如果您不想使用整个Guava库,只需获取其源代码)。 有关更完整的基准测试解决方案,请查看同一团队的Caliper 。

这两个都基于System.nanoTime() ,您应该优先于System.currentTimeMillis()来测量经过的时间。 基本原因是System.currentTimeMillis()是一个“时钟”(试图返回System.nanoTime()时间),而System.nanoTime()是一个“计时器”(它尝试从某个任意点返回时间)。

当你想要弄清楚单个事件发生的时候,你想要一个时钟,所以你可以用你的手表或墙上的时钟(或其他计算机上的时钟)排队。 但它不适合测量同一系统上两个事件之间的经过时间,因为计算机偶尔会调整其内部时钟对应于挂壁时间的概念。 例如,如果你这样做

 long timeA = System.currentTimeMillis(); doStuff(); long timeB = System.currentTimeMillis(); System.out.println("Elapsed time: " + (timeB - timeA)); 

如果在执行doStuff()时NTP向后调整,则可能会得到否定结果。 System.nanoTime() ,作为计时器而不是时钟,应该忽略该调整,从而避免这个问题。

(请注意,以上所有内容都是概念性的;不幸的是,在实现级别上事情可能会变得混乱。但这并不会改变建议: System.nanoTime()应该是您可以在平台上获得的最佳计时器,而System.currentMilliseconds()应该是你能得到的最佳时钟。)

System.nanoTime(); 也许,正是你在寻找的。 并添加标准偏差和平均时间的计算。

您应该考虑多次运行算法并对结果求平均值。

这有三个原因:

  1. 由于您已确定的原因,它使计时更容易。

  2. JVM“预热”并且代码的性能将会改变:热点JVM在您运行多次方法之前不会完全编译。 如果你没有通过这个,你的结果就不具代表性。

  3. 平均时间,避免因GC等外部事件或计算机上运行的其他事件造成的虚假影响总是一个好主意。

根据经验,尝试将algos运行10,000次作为热身,然后运行10,000次。 修改数字以适合您的运行时…

这是一篇解释同样事情的文章 。

您可以检测代码并计算执行的字节码数。 你可以用bycounter做到这一点 。

这可能不适合您的目的。 如果程序只有很少的字节码,则可能无法准确测量哪个程序实际上更高效,因为执行字节码的成本可能会有很大差异。 此外,如果在程序期间有网络或磁盘读取,字节码计数可能会给出错误的比较。