Точное измерение времени на Java - PullRequest
16 голосов
/ 01 октября 2009

Java дает доступ к двум методам получения текущего времени: System.nanoTime() и System.currentTimeMillis(). Первый дает результат в наносекундах, но фактическая точность намного хуже, чем у этого (много микросекунд).

JVM уже обеспечивает наилучшее возможное значение для каждой конкретной машины? Иначе, есть ли какая-нибудь библиотека Java, которая может дать более точное измерение, возможно, будучи привязанной к конкретной системе?

Ответы [ 5 ]

15 голосов
/ 01 октября 2009

Проблема с получением сверхточных измерений времени состоит в том, что некоторые процессоры не могут / не обеспечивают такие крошечные приращения.

Насколько я знаю, System.currentTimeMillis() и System.nanoTime() - это лучшее измерение, которое вы сможете найти.

Обратите внимание, что оба возвращают значение long.

5 голосов
/ 01 октября 2009

Это немного бессмысленно в Java измерять время вплоть до наносекундного масштаба; случайное попадание в GC легко уничтожит любую точность, которую это могло дать. В любом случае, в документации говорится, что хотя она дает точность наносекунды, это не то же самое, что точность наносекунды; и есть операционные системы, которые ни в коем случае не сообщают о наносекундах (именно поэтому вы найдете ответы с квантованием до 1000 при обращении к ним; это не удача, а ограничение).

Мало того, но в зависимости от того, как эта функция на самом деле реализована в ОС, вы все равно можете найти квантованные результаты (например, ответы, которые всегда заканчиваются на 64 или 128 вместо промежуточных значений).

Стоит также отметить, что цель метода - найти две разницы во времени между некоторым (близким) временем начала и сейчас; если вы возьмете System.nanoTime () в начале долго работающего приложения, а затем возьмете System.nanoTime () долгое время спустя, возможно, он сместился довольно далеко от реального времени. Таким образом, вы должны действительно использовать его только в течение периодов менее 1 с; если вам нужно более продолжительное время работы, миллисекунд должно быть достаточно. (А если это не так, то наберите последние несколько цифр; вы, вероятно, поразите клиентов, и результат будет таким же действительным.)

1 голос
/ 01 октября 2009

К сожалению, я не думаю, что Java RTS достаточно зрелый в данный момент.

Время Java пытается предоставить лучшее значение (они фактически делегируют нативный код для вызова, чтобы получить время ядра). Однако спецификации JVM делают этот грубый отказ от измерения времени главным образом для таких вещей, как действия GC и поддержка базовой системы.

  • Некоторые действия GC блокируют все потоки, даже если вы используете одновременный сборщик мусора.
  • Тиковая тактовая частота Linux по умолчанию составляет всего 10 мс. Java не может сделать это лучше, если linux kernal не поддерживает.

Я не понял, как обратиться к # 1, если вашему приложению не требуется GC. Приличное и среднего размера приложение, вероятно, время от времени тратит десятки миллисекунд на паузы ГХ. Возможно, вам не повезло, если ваше требование к точности ниже 10 мс.

Что касается # 2, вы можете настроить linux kernal , чтобы повысить точность. Тем не менее, вы также получаете меньше из своей коробки, потому что теперь Kernal контекст переключается чаще.

Возможно, нам следует взглянуть на это под другим углом. Есть ли причина, по которой OPS нуждается в точности на 10 мс ниже? Можно ли сказать Ops, что точность составляет 10 мс, а также посмотреть журнал GC в это время, чтобы они знали, что время точно + -10 мс без активности GC в это время?

0 голосов
/ 25 января 2017

JNI: создайте простую функцию для доступа к инструкции Intel RDTSC или регистру PMCCNTR сопроцессора p15 в ARM.

Чистая Java: Вы можете получить лучшие значения, если хотите отложить дочасы тик.Вы можете вращать проверку System.nanoTime (), пока значение не изменится.Например, если вы знаете, что значение System.nanoTime () меняется каждые 10000 итераций цикла на вашей платформе на величину DELTA, тогда фактическое время события было finalNanoTime-DELTA * ITERATIONS / 10000.Вам нужно будет "прогреть" код перед выполнением реальных измерений.

Взлом (только для профилирования и т. Д.): Если сборщик мусора отбрасывает вас, вы всегда можете измерить время, используя высокий приоритетпоток работает во втором jvm, который не создает объекты.Пусть он вращается, увеличивая длину в общей памяти, которую вы используете в качестве часов.

0 голосов
/ 01 октября 2009

Если вы хотите записать какое-то явление порядка наносекунд, вам действительно нужна операционная система реального времени . Точность таймера будет в значительной степени зависеть от реализации операционной системой таймера высокого разрешения и используемого оборудования.

Однако вы все равно можете остаться с Java, поскольку доступны версии RTOS.

...