Подтвердить что ты не робот

Точность и точность System.nanoTime()

Документация для System.nanoTime() гласит следующее (основное внимание).

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

Как я вижу, это можно интерпретировать двумя разными способами:

  • Предложение в жирным выше относится к отдельным возвращаемым значениям. Затем точность и точность следует понимать в численном смысле. То есть, точность относится к числу значимых цифр - положению усечения, а точность заключается в том, является ли число правильным (например, описанное в верхнем ответе здесь В чем разница между "точностью" и "точностью" ?)

  • Предложение в жирный выше относится к возможности самого метода. Затем точность и точность следует понимать как иллюстрированные аналоги мишени (http://en.wikipedia.org/wiki/Precision_vs._accuracy#Accuracy_versus_precision:_the_target_analogy). Таким образом, низкая точность, высокая точность = > неправильное значение неоднократно ударяется с высокой точностью: воображая, что физическое время стоит на месте, последовательные вызовы nanoTime() возвращают одно и то же числовое значение, но оно отключено от фактического прошедшего времени, так как отсчета времени с помощью некоторой константы смещения.

Какая интерпретация является правильной? Моя точка зрения заключается в том, что интерпретация 2 означает, что измерение разницы во времени с использованием nanoTime() путем вычитания двух возвращаемых значений будет правильным для наносекунды (поскольку постоянная ошибка/смещение в измерении будет устранена), тогда как интерпретация 1 будет 't гарантировать такое соответствие между измерениями и, следовательно, не обязательно будет означать высокую точность измерений разницы во времени.


Обновлено 4/15/13: Документация по Java 7 для System.nanoTime() обновлена ​​до адреса возможная путаница с предыдущей формулировкой.

Возвращает текущее значение текущего источника времени с высокой разрешающей способностью Java Virtual Machine, в наносекундах.

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

Этот метод обеспечивает наносекундную точность, но не обязательно наносекундное разрешение (то есть, как часто изменяется значение) - никаких гарантий не сделано, за исключением того, что разрешение не хуже, чем разрешение currentTimeMillis().

Различия в последовательных вызовах, которые охватывают более 292 лет (2 63 наносекунды), не будут правильно вычислять прошедшее время из-за численного переполнения.

Значения, возвращаемые этим методом, становятся значимыми только тогда, когда вычисляется разница между двумя такими значениями, полученными в одном экземпляре виртуальной машины Java.

4b9b3361

Ответ 1

Первая интерпретация верна. В большинстве систем три наименее значимые цифры всегда будут равны нулю. Это фактически дает микросекундную точность, но сообщает об этом на фиксированном уровне точности наносекунды.

Фактически, теперь, когда я снова смотрю на это, ваша вторая интерпретация также является достоверным описанием того, что происходит, может быть, даже более того. Представляя время замерзания, в отчете всегда будет одинаковое количество наносекунд, но правильное, если понимать его как целое число микросекунд.

Ответ 2

В командной строке Clojure я получаю:

user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
-641
user=> (- (System/nanoTime) (System/nanoTime))
0
user=> (- (System/nanoTime) (System/nanoTime))
-642
user=> (- (System/nanoTime) (System/nanoTime))
-641
user=> (- (System/nanoTime) (System/nanoTime))
-641

Таким образом, nanoTime не обновляется каждую наносекунду, вопреки тому, что можно было бы интуитивно ожидать от ее точности. В системах Windows он использует API QueryPerformanceCounter под капотом (согласно в этой статье), что на практике, похоже, дает примерно 640 нс разрешение (в моей системе!).

Заметим, что nanoTime само по себе не может иметь никакой точности, поскольку его абсолютное значение произвольно. Разница между последовательными вызовами nanoTime имеет смысл. Точность этой разности находится в шаге 1 микросекунды.

Ответ 3

Одна довольно интересная особенность разницы между System.currentTimeMillis() и System.nanoTime() заключается в том, что System.nanoTime() НЕ меняется с настенными часами. Я запускаю код на виртуальной машине Windows с большим временным дрейфом. System.currentTimeMillis() может перепрыгивать назад или вперед на 1-2 секунды каждый раз, когда NTP исправляет этот дрейф, делая точные метки времени бессмысленными. (Выпуски VPS Windows 2003, 2008)

System.nanoTime(), однако, не влияет на изменение времени настенных часов, поэтому вы можете взять время, полученное через NTP, и применить исправление на основе System.nanoTime(), так как NTP был проверен последним, и у вас есть гораздо более точное время, чем System.currentTimeMillis() в неблагоприятных условиях настенных часов

Это, конечно, интуитивно понятное, но полезно знать

Ответ 4

Если кто-то вроде меня приходит и читает этот вопрос снова и снова, чтобы все еще понять его, вот более простое (я надеюсь) объяснение.

Precision о том, сколько цифр вы сохраняете. Каждый из:

long start = System.nanoTime();
long end   = System.nanoTime();

будет точным числом (много цифр).

Так как accuracy измеряется только по сравнению с чем-то, индивидуальный вызов System.nanoTime не имеет смысла, поскольку он является довольно произвольным и не зависит от того, что мы можем измерить. Единственный способ отличить его от точности - это два разных вызова, например:

 long howMuch = end - start;

не будет иметь нано-секундную точность. А ведь на моей машине разница составляет 0,2 - 0,3 микросекунды.