1

为什么这段代码

    long s, e, sum1 = 0, sum2 = 0, TRIALS = 10000000;

    for(long i=0; i<TRIALS; i++) {
        s = System.nanoTime();
        e = System.nanoTime();
        sum1 += e - s;            
        s = System.nanoTime();
        e = System.nanoTime();
        sum2 += e - s;
    }        
    System.out.println(sum1 / TRIALS);
    System.out.println(sum2 / TRIALS);

产生这个结果

-60  
61 

“在我的机器上?”

编辑:
我是 Sam 的回答指向 nanoSecond() 文档,该文档有帮助,但现在,更准确地说,为什么结果始终有利于第一个总和?

“我的机器”:
JavaSE-1.7、Eclipse
Win 7 x64、AMD Athlon II X4 635

在循环内切换顺序会产生相反的结果

for(int i=0; i<TRIALS; i++) {            
    s = System.nanoTime();
    e = System.nanoTime();
    sum2 += e - s;            
    s = System.nanoTime();
    e = System.nanoTime();
    sum1 += e - s;
}  
61
-61  

在将其添加到 sum1 之前查看 (es) 会使 sum1 为正。

for(long i=0; i<TRIALS; i++) {
    s = System.nanoTime();
    e = System.nanoTime();
    temp = e-s;
    if(temp < 0)
        count++;
    sum1 += temp;

    s = System.nanoTime();
    e = System.nanoTime();
    sum2 += e - s;
}
61  
61

正如 Andrew Alcock 指出的那样, sum1 += -s + e 产生了预期的结果。

for(long i=0; i<TRIALS; i++) {
    s = System.nanoTime();
    e = System.nanoTime();
    sum1 += -s + e;

    s = System.nanoTime();
    e = System.nanoTime();
    sum2 += -s + e;
}
61
61

其他一些测试: http: //pastebin.com/QJ93NZxP

4

3 回答 3

2

这个答案是假设。如果您使用有关您的环境的一些详细信息更新您的问题,那么其他人可能会给出更详细、更扎实的答案。

nanoTime()功能通过访问一些具有低访问延迟的高分辨率计时器来工作。在 x86 上,我相信这是Time Stamp Counter,它由机器的基本时钟周期驱动。

如果您看到 +/- 60 ns 的一致结果,那么我相信您只是看到了机器上计时器的基本间隔。

但是,负数呢?再次假设,但如果您阅读 Wikipedia 文章,您会看到英特尔处理器可能会重新排序指令的评论。

于 2013-01-02T22:39:48.967 回答
1

结合 roundar,我们对这段代码进行了许多测试。总之,在以下情况下效果消失了:

  1. 在解释模式下运行相同的代码 (-Xint)
  2. 将聚合逻辑顺序从更改sum += e - ssum += -s + e
  3. 在一些不同的架构或不同的虚拟机上运行(例如,我在 Mac 上的 Java 6 上运行)
  4. 放置日志语句检查 s 和 e
  5. 对 s 和 e 执行附加算术

另外,效果不是线程:

  1. 没有产生额外的线程
  2. 只涉及局部变量
  3. 这种效果在 roundar 环境中是 100% 可重现的,并且总是产生完全相同的时序,即 +61 和 -61。

效果不是时间问题,因为:

  1. 执行超过 10m 次迭代
  2. 这种效果在圆形环境中是 100% 可重现的
  3. 结果在所有迭代中都是完全相同的时间,即 +61 和 -61。

鉴于上述情况,我相信我们在 Java VM 的热点模块中存在错误。编写的代码应该返回积极的结果,但没有。

于 2013-01-03T10:07:44.170 回答
0

直接来自oracle 的文档

简而言之:更新值的频率可能会导致结果不同。

纳米时间

公共静态长纳米时间()

返回最精确的可用系统计时器的当前值,以纳秒为单位。

此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。

返回的值表示自某个固定但任意时间以来的纳秒(可能在将来,因此值可能为负数)。此方法提供纳秒精度,但不一定提供纳秒精度。不保证值的变化频率。由于数值溢出,超过大约 292 年(263 纳秒)的连续调用的差异将无法准确计算经过的时间。

For example, to measure how long some code takes to execute:

   long startTime = System.nanoTime();
   // ... the code being measured ...
   long estimatedTime = System.nanoTime() - startTime;
 

Returns:
    The current value of the system timer, in nanoseconds.
Since:
    1.5
于 2013-01-02T22:23:32.667 回答