本文介绍了为什么我的System.nanoTime()坏了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我自己和我这个时代的另一位开发人员最近从工作中的Core 2 Duo机器转移到新的Core 2 Quad 9505;两者都使用JDK 1.6.0_18运行Windows XP SP3 32位。

Myself and another developer on my time recently moved from a Core 2 Duo machine at work to a new Core 2 Quad 9505; both running Windows XP SP3 32-bit with JDK 1.6.0_18.

这样做,我们对一些时序/统计/指标聚合代码进行了一些自动单元测试开始失败,因为似乎是从System.nanoTime()返回的荒谬值。

Upon doing so, a couple of our automated unit tests for some timing/statistics/metrics aggregation code promptly started failing, due to what appear to be ridiculous values coming back from System.nanoTime().

在我的机器上可靠地显示此行为的测试代码是:

Test code that shows this behaviour, reliably, on my machine is:

import static org.junit.Assert.assertThat;

import org.hamcrest.Matchers;
import org.junit.Test;

public class NanoTest {

  @Test
  public void testNanoTime() throws InterruptedException {
    final long sleepMillis = 5000;

    long nanosBefore = System.nanoTime();
    long millisBefore = System.currentTimeMillis();

    Thread.sleep(sleepMillis);

    long nanosTaken = System.nanoTime() - nanosBefore;
    long millisTaken = System.currentTimeMillis() - millisBefore;

    System.out.println("nanosTaken="+nanosTaken);
    System.out.println("millisTaken="+millisTaken);

    // Check it slept within 10% of requested time
    assertThat((double)millisTaken, Matchers.closeTo(sleepMillis, sleepMillis * 0.1));
    assertThat((double)nanosTaken, Matchers.closeTo(sleepMillis * 1000000, sleepMillis * 1000000 * 0.1));
  }

}

典型输出:

millisTaken=5001
nanosTaken=2243785148

运行100x会使纳米结果在实际睡眠时间的33%到60%之间;通常只有40%左右。

Running it 100x yields nano results between 33% and 60% of the actual sleep time; usually around 40% though.

我理解Windows中计时器准确性的弱点,并且读过相关的线程,如,但我的理解是System.nanoTime()仅用于我们的目的'使用它: - 测量经过的时间;比currentTimeMillis()更准确。

I understand the weaknesses in accuracy of timers in Windows, and have read related threads like Is System.nanoTime() consistent across threads?, however my understanding is that System.nanoTime() is intended for exactly the purpose we're using it :- measuring elapsed time; more accurately than currentTimeMillis().

有谁知道为什么它会返回如此疯狂的结果?这可能是硬件架构问题(唯一重要的是这台机器上的CPU /主板)?使用我当前硬件的Windows HAL存在问题?一个JDK问题?我应该放弃nanoTime()吗?我应该在某个地方记录错误,还是有关我如何进一步调查的任何建议?

Does anyone know why it's returning such crazy results? Is this likely to be a hardware architecture problem (the only major thing that has changed is the CPU/Motherboard on this machine)? A problem with the Windows HAL with my current hardware? A JDK problem? Should I abandon nanoTime()? Should I log a bug somewhere, or any suggestions on how I could investigate further?

UPDATE 19/07 03:15 UTC :尝试后下面的finnw的测试用例我做了一些谷歌搜索,遇到了诸如上安装补丁。也许我应该在公司桌面构建团队中解决这个问题?

I'm a bit confused about why this was still an issue though; from my reading I thought TSC vs PMT issues were largely resolved in Windows XP SP3. Could it be because my machine was originally SP2, and was patched to SP3 rather than installed originally as SP3? I now also wonder whether I should be installing patches like the one at MS KB896256. Maybe I should take this up with the corporate desktop build team?

推荐答案

问题得到解决(对于适用性有一些公开的怀疑nanoTime()在多核系统上的应用!)将 / usepmtimer 添加到 C:\ boot.ini 字符串的末尾;强制Windows使用电源管理计时器而不是TSC。这是一个悬而未决的问题,为什么我需要这样做,因为我使用的是XP SP3,因为我知道这是默认设置,但也许是因为我的机器被修补到SP3的方式。

The problem was resolved (with some open suspicions about the suitability of nanoTime() on multi-core systems!) by adding /usepmtimer to the end of my C:\boot.ini string; forcing Windows to use the Power Management timer rather than the TSC. It's an open question as to why I needed to do this given I'm on XP SP3, as I understood that this was the default, however perhaps it was due to the manner in which my machine was patched to SP3.

这篇关于为什么我的System.nanoTime()坏了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 10:47