Java高精度秒表

4
我有一个问题,我不知道如何解决它。
我需要测量执行某个函数所需的时间。秒表函数可以测量毫秒级别的时间,但不够精确,因此我使用了纳秒级别的测量方法。
问题在于,这个函数结束得非常快,即使使用纳秒级别的秒表也无法测量到它。
我知道秒表是可以工作的,因为我尝试在我的函数中加入例如Thread.sleep(1)(Thread.sleep是以毫秒为单位计量的),并且我能得到时间,但是没有Thread.sleep,我的时间总是0。 有什么建议吗?
这是我的代码:
long startTimeLocalNS=0;
long stopTimeLocalNS = 0;
startTimeLocalNS = System.nanoTime();
if (something)
{
    /*my Code;*/
}   
stopTimeLocalNS = System.nanoTime();
disconnectTime = (stopTimeLocalNS - startTimeLocalNS);

你确定 something == true 吗? - Peter Lawrey
2
如果需要这么短的时间,你为什么还在意它花费了多长时间?微基准测试通常会在预热后使用循环。更有用的基准测试会执行一些有用的操作。 - Tom Hawtin - tackline
有没有可能某些东西会优化掉第二个调用,并只使用第一个值? - cHao
1
@Peter 是的,something == true,那是百分之百的。我会在系统上搜索我的纳秒时钟的精度。那应该有所帮助。@Tom 好的,我需要那个时间。如果不需要,我也不会请求帮助... =] - CRT_flow
@Rich,说得好。应该是 long start = System.nanoTime(); long time = System.nanoTime() - start,干杯。 - Peter Lawrey
显示剩余7条评论
7个回答

7
如何在循环中运行函数数千次(或数百万次),测量总时间并将其除以迭代次数?但要注意编写微基准测试的许多陷阱。

我的函数有点特殊,不能运行超过1次。但是,如果我总是得到我的纳秒时钟无法测量的时间,并将其除以迭代次数,那么我又会得到0时间吗? - CRT_flow
@CRT_flow:不确定你的意思。而且你的要求听起来有些荒谬。我敢说,你不能运行该函数超过一次是不可能的。 - Michael Borgwardt
我认为@CRT_flow认为你正在计时每个方法的调用。 - Rich
@CRT_flow:Michael建议您计时X百万次调用的总时间,并将其除以调用次数。他并不建议您调用X百万次并计时每个调用。 - Rich

1
你可以这样做:
long startTimeLocalNS=0;
long stopTimeLocalNS = 0;
int count = 10000;
startTimeLocalNS = System.nanoTime();
if (something)
{
    while(count-- != 0) {
    /*my Code;*/
    }
}   
stopTimeLocalNS = System.nanoTime();
disconnectTime = (stopTimeLocalNS - startTimeLocalNS) / count;

1

你可以循环执行要测量的代码1000次,然后将纳秒差除以1000。


1

你正在对一些代码进行性能分析吗?如果是的话,市场上提供的性能分析工具会做得更好。

如果你只需要测量非常短的时间段,你有几个选择:

  • System.currentTimeMillis() - 在我的电脑上它有60Hz的分辨率,大约为16ms的精度
  • System.nanoTime() - 应该更准确,但我听说在多核CPU时代它不是最快的解决方案
  • JNI - 用C语言来测量时间,但JNI调用的成本将是显著的。

你能否提供几个可用的性能分析器?最好是开源的。 - sheki
当然,jvisualvm是免费的,拥有内置分析器(但我从未尝试过)。我知道JProfiler非常好用,很多人也建议使用Yourkit。 - Tomasz Nurkiewicz

0
一个出乎意料的答案:正如Peter Lawrey所说,当比较两个nanoTime()调用时,大多数系统应该返回一个大于零的数字作为结果。然而,您是否绝对确定您正在比较正确的值?您可能会不小心这样做:
long startTime = System.nanoTime();
if (something)
{
    /*my Code;*/
}
long stopTime = System.nanoTime();
disconnectTime = stopTime - stopTime; //note the error - you are subtracting stoptime from itself

所以,我的问题是,你的代码中是否存在一个你在上面的示例代码中没有复制的错误?
第二个问题,你确定 something==true 吗?

是的,我确定我的if语句是正确的,而且我没有做stopTime - stopTime =] - CRT_flow
好的 - 我想我只是问一下 :) - Rich
有没有办法可以暂停秒表一段时间,然后继续计时器。我还没有找到合适的答案。 - slaveCoder

0

如果你想对你的函数进行基准测试,最简单的方法是在一个测量内多次运行它。然后将时间除以调用次数。


正如我所说,我的函数是特定的,只能测量一次...此外,完成我的程序需要更长的时间,因此这是一个有点混乱的解决方案,以我个人的看法。 - CRT_flow

0

无论 JVM 是否已经预热,你将会得到非常不同的答案。对于那些你会多次调用的非常短的序列,你应该计算重复它们所需的时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接