Я и еще один разработчик в свое время недавно перешли с компьютера Core 2 Duo на работе на новый Core 2 Quad 9505; оба работают под управлением 32-разрядной версии Windows XP SP3 с JDK 1.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
Запуск его 100x дает нано-результаты от 33% до 60% фактического времени сна; обычно около 40%.
Я понимаю слабые места в точности таймеров в Windows и читал связанные темы, такие как Is System. nanoTime () согласован между потоками?, однако я понимаю, что System.nanoTime () предназначен именно для той цели, которую мы используем: - измерение прошедшего времени; точнее, чем currentTimeMillis ().
Кто-нибудь знает, почему он возвращает такие сумасшедшие результаты? Вероятно, это проблема аппаратной архитектуры (единственное, что изменилось, - это процессор / материнская плата на этой машине)? Проблема с Windows HAL на моем текущем оборудовании? Проблема с JDK? Стоит ли отказываться от nanoTime ()? Должен ли я где-то регистрировать ошибку или какие-либо предложения о том, как я могу продолжить расследование?
ОБНОВЛЕНИЕ 19/07, 03:15 UTC: попробовав приведенный ниже тестовый пример finnw, я еще раз погуглил, наткнувшись на такие записи, как bugid: 6440250. Это также напомнило мне о другом странном поведении, которое я заметил поздно в пятницу, когда пинги возвращались отрицательно. Итак, я добавил / usepmtimer в свой boot.ini, и теперь все тесты работают, как ожидалось, и мои пинги тоже нормальные.
Я немного сбит с толку, почему это все еще оставалось проблемой; Из моего чтения я подумал, что проблемы TSC и PMT в значительной степени решены в Windows XP SP3. Может быть, это потому, что моя машина изначально была с пакетом обновления 2 (SP2) и была исправлена до SP3, а не была изначально установлена как SP3? Теперь я также задаюсь вопросом, следует ли мне устанавливать исправления, подобные тому, что находится на MS KB896256. Может, мне стоит обсудить это с командой разработчиков корпоративных настольных компьютеров?