私自身と私の時代の別の開発者は、最近、仕事中のCore2Duoマシンから新しいCore2Quad9505に移行しました。どちらもWindowsXPSP332ビットとJDK1.6.0_18を実行しています。
そうすると、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
100倍実行すると、実際の睡眠時間の33%から60%のナノ結果が得られます。通常は約40%です。
Windowsのタイマーの精度の弱点を理解し、System.nanoTime()のような関連スレッドをスレッド間で一貫して読んだことがありますか?ただし、私の理解では、System.nanoTime()は、使用している目的を正確に目的としています。経過時間の測定。currentTimeMillis()よりも正確です。
なぜそれがそのようなクレイジーな結果を返すのか誰かが知っていますか?これはハードウェアアーキテクチャの問題である可能性がありますか(変更された唯一の主要なものはこのマシンのCPU /マザーボードです)?現在のハードウェアでのWindowsHALに問題がありますか?JDKの問題?nanoTime()を放棄する必要がありますか?どこかにバグを記録する必要がありますか、それともさらに調査する方法についての提案がありますか?
UPDATE 19/07 03:15 UTC:以下のfinnwのテストケースを試した後、さらにグーグルを実行し、 bugid:6440250などのエントリに出くわしました。また、金曜日の終わりにpingがネガティブに戻ってきていることに気付いた他の奇妙な行動を思い出しました。そこで、boot.iniに/ usepmtimerを追加すると、すべてのテストが期待どおりに動作し、pingも正常になりました。
しかし、なぜこれがまだ問題であったのかについて少し混乱しています。私の読書から、TSCとPMTの問題はWindowsXPSP3でほぼ解決されたと思いました。私のマシンが元々SP2であり、元々SP3としてインストールされていたのではなく、SP3にパッチが適用されていたことが原因でしょうか?また、 MSKB896256のようなパッチをインストールする必要があるかどうかも疑問に思います。たぶん私はこれを企業のデスクトップビルドチームに取り上げるべきでしょうか?