我和我的另一位开发人员最近从工作中的Core 2 Duo机器迁移到新的Core 2 Quad 9505;两者都使用JDK 1.6.0_18运行Windows XP SP3 32位。为什么我的System.nanoTime()被破坏?
一旦这样做,由于什么似乎是从System.nanoTime()返回的荒谬的值,我们的一些时间/统计/指标聚合代码的自动单元测试立即开始失败。
显示此问题,可靠地,我的机器上测试代码是:
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%左右。我知道Windows中定时器的精确性的弱点,并且已经阅读了相关的线程,比如Is System.nanoTime() consistent across threads?,但是我的理解是System.nanoTime()的目的正是为了我们使用它的目的: - 测量已用时间;比currentTimeMillis()更准确。
有谁知道它为什么会返回这样疯狂的结果吗?这可能是一个硬件架构问题(唯一主要的改变是这台机器上的CPU /主板)? Windows HAL与我目前的硬件有问题? JDK问题?我应该放弃nanoTime()吗?我应该在什么地方记录一个错误,或者有关我如何进一步调查的建议?
UPDATE 19/07 03:15 UTC:在尝试下面的finnw测试用例之后,我做了一些更多的谷歌搜索,碰到一些条目,如bugid:6440250。这也让我想起了周五晚些时候我注意到的其他一些奇怪的行为,在那里ping回来了。所以我在我的boot.ini中加入了/usepmtimer,现在所有的测试都按照预期运行,并且我的ping也是正常的。
我有点困惑,为什么这仍然是一个问题,虽然;从我的阅读中,我认为TSC vs PMT问题在Windows XP SP3中得到了很大程度的解决。难道是因为我的机器最初是SP2,并且已经修补到SP3而不是最初安装为SP3?我现在也想知道我是否应该安装像MS KB896256那样的补丁。也许我应该将这与企业桌面构建团队一起考虑?
你得到一个完全新的机器或者是在当前计算机升级保留旧的Windows安装? – 2010-07-18 09:00:58
全新机器;在企业标准构建中重建。 – Chad 2010-07-18 09:02:42
工作正常,我的Windows 7下的64位最新的JDK 6 – TofuBeer 2010-07-18 09:02:48