Точное измерение времени в Java
Java дает доступ к двум методам для получения текущего времени:System.nanoTime()
и System.currentTimeMillis()
. Первый дает результат в наносекундах, но фактическая точность намного хуже (много микросекунд).
JVM уже обеспечивает наилучшее возможное значение для каждой конкретной машины? В противном случае, есть ли какая-то библиотека Java, которая может дать более точное измерение, возможно, будучи привязанной к определенной системе?
5 ответов
проблема с получением супер точных измерений времени заключается в том, что некоторые процессоры не могут/не обеспечивают такие крошечные приращения.
насколько я знаю, System.currentTimeMillis()
и System.nanoTime()
Это лучшее измерение, которое вы сможете найти.
обратите внимание, что оба возвращают long
значение.
Это немного бессмысленно в Java, измеряющем время до наносекундной шкалы; случайный удар GC легко уничтожит любую точность, которую это могло дать. В любом случае, в документации говорится, что, хотя она дает наносекундную точность, это не то же самое, что наносекундная точность; и есть операционные системы, которые в любом случае не сообщают о наносекундах (поэтому вы найдете ответы, квантованные до 1000 при доступе к ним; это не удача, это ограничение).
не только это, но и в зависимости от того, как функция фактически реализована ОС, вы можете найти квантованные результаты, проходящие в любом случае (например, ответы, которые всегда заканчиваются на 64 или 128 вместо промежуточных значений).
также стоит отметить, что цель метода состоит в том, чтобы найти две разницы во времени между некоторым (близлежащим) временем начала и сейчас; если вы берете систему.nanoTime () в начале долгосрочного приложения, а затем взять систему.nanoTime() долгое время позже он, возможно, дрейфовал довольно далеко от реального времени. Таким образом, вы должны использовать его только для периодов меньше 1s; если вам нужно больше времени работы, миллисекунд должно быть достаточно. (А если нет, то составьте несколько последних номеров; вы, вероятно, произведете впечатление на клиентов, и результат будет таким же действительным.)
к сожалению, я не думаю, что java RTS достаточно зрелая на данный момент.
Java time пытается предоставить лучшее значение (они фактически делегируют собственный код для вызова get время ядра). Однако спецификации JVM делают этот грубый отказ от измерения времени в основном для таких вещей, как деятельность GC и поддержка базовой системы.
- некоторые действия GC будут блокировать все потоки, даже если вы используете параллельный GC.
- часы linux по умолчанию точность тика только 10ms. Java не может сделать его лучше, если ядро linux не поддерживает.
Я не понял, как адрес #1, Если ваше приложение не нужно делать GC. Приличное приложение и размер med, вероятно, и иногда тратит десятки миллисекунд на паузы GC. Вы, вероятно, не повезло, если ваше требование точности ниже 10ms.
Что касается #2, Вы можете настройка ядра linux чтобы дать более точный. Однако, вы также получаете меньше из вашей коробки, потому что теперь чаще переключайтесь на контекст ядра.
возможно, мы должны посмотреть на него под другим углом. Есть ли причина, по которой OPS нужна точность 10 мс ниже? Можно ли сказать Ops, что точность составляет 10 мс, а также посмотреть на журнал GC в то время, чтобы они знали, что время +-10 мс точно без активности GC в это время?
Если вы хотите записать какой-то тип явления порядка наносекунд, вам действительно нужно операционная система в реальном времени. Точность таймера будет во многом зависеть от реализации операционной системой его таймер высокого разрешения и базовое оборудование.
тем не менее, вы все равно можете остаться с Java, так как доступны версии RTOS.
JNI, у: Создайте простую функцию для доступа к инструкции Intel RDTSC или регистру PMCCNTR сопроцессора p15 в ARM.
Чистая Java: Вы можете получить лучшие значения, если вы готовы отложить до тикающих часов. Вы можете вращать систему проверки.nanoTime() пока значение не изменится. Если вы знаете, например, что значение System.nanoTime() изменяет каждые 10000 итераций цикла на вашей платформе на дельту суммы, тогда фактическое время события было finalNanoTime-Дельта * итерации/10000. Вам нужно будет "прогреть" код, прежде чем принимать фактические измерения.
Hack (только для профилирования и т. д.): Если сборка мусора выбрасывает вас, вы всегда можете измерить время, используя высокоприоритетный поток, запущенный во второй jvm, который не создает объекты. Пусть он вращается, увеличивая длинную общую память, которую вы используете в качестве часов.