用Java测量时间

用Java测量时间,java,performance,time,profiling,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 do

因此,我试图测量两种不同算法实现完成给定任务所需的时间,结果如下:

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;
}
与使用
System.currentTimeMillis()
相比,获得更真实结果(而不是0.0,这显然不是真的!)的更好方法是什么?我知道我可以一次又一次地运行这些算法并总结它们的结果,但我有一种直觉,在Java中可能有一种更可靠的方法来测量经过的时间(如果可能的话,
real
user
sys


谢谢

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

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

这两种方法都基于
System.nanoTime()
,您应该更喜欢使用
System.currentTimeMillis()
来测量经过的时间。基本原因是
System.currentTimeMillis()
是一个“时钟”(尝试返回墙上的时间),而
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.currentmilless()
应该是您可以获得的最佳时钟。)

你应该考虑多次运行算法并平均结果。

原因有三:

  • 由于您已经确定的原因,它使计时变得更容易

  • JVM会“预热”,代码的性能也会随之改变:热点JVM在您大量运行一个方法之前不会完全编译。如果你不能克服这一点,你的结果将不具有代表性

  • 计算时间的平均值总是一个好主意,以避免由于外部事件(如GC)或计算机上运行的其他东西而产生的虚假影响

  • 根据经验,试着在热身时运行你的algos 10000次,然后再运行10000次。修改数字以适合您的运行时


    解释同样的事情。

    您可以插入代码并计算执行的字节码数。你可以用它来做这件事


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

    当你测量很短的时间间隔时,你最终测量的测量逻辑比你测量的预期“目标”要多。那么运行每个alg一百万次有什么问题?随机参数?回答得好。还有一件事,当我唯一想比较两种算法时,我是不是最好在启用-Xint标志的情况下运行JVM,这样我就不必担心奇怪的JIT效果了?当然,您对比较正常操作(包括编译)下的算法性能感兴趣?在这种情况下,绝对不是-解释的运行时可能是无关的。你大概是在比较它们,因为在一些更大的应用程序中使用时,性能对你很重要?如果您不在现实环境中运行测试,那么结果本身就不现实。重要提示:对于OP所描述的基准测试,Guava团队建议使用。