用Java测量时间

时间:2012-02-26 23:16:04

标签: java performance time profiling

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

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,如果可能的话!)。

由于

4 个答案:

答案 0 :(得分:6)

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

这两个都基于System.nanoTime(),您应该优先于System.currentTimeMillis()来衡量已用时间。基本原因是System.currentTimeMillis()是一个"时钟" (试图返回壁垒时间)而System.nanoTime()是一个"计时器" (试图从任意点开始返回时间)。

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

long timeA = System.currentTimeMillis();
doStuff();
long timeB = System.currentTimeMillis();
System.out.println("Elapsed time: " + (timeB - timeA));
如果NTP在执行doStuff()时向后调整,则可能会得到否定结果。 System.nanoTime(),作为计时器而不是时钟,应该忽略该调整,从而避免这个问题。

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

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

这有三个原因:

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

  2. JVM"热身"并且代码的性能将会发生变化:热点JVM不会完全编译,直到你多次运行一个方法。如果您没有通过此结果,您的结果将无法代表。

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

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

    Here's an article解释同样的事情。

答案 3 :(得分:1)

您可以检测代码并计算执行的字节码数。您可以使用bycounter执行此操作。

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