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