我和我的另一位開發人員最近從工作中的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