segundos nanosegundos java nanotime

java - nanosegundos - Precisión vs. exactitud de System.nanoTime()



nanosegundos a segundos java (4)

La documentación para System.nanoTime() dice lo siguiente (el énfasis es mío).

Este método solo se puede utilizar para medir el tiempo transcurrido y no está relacionado con ninguna otra noción del sistema o del reloj de pared. El valor devuelto representa nanosegundos desde un tiempo fijo pero arbitrario (quizás en el futuro, por lo que los valores pueden ser negativos). Este método proporciona una precisión de nanosegundos, pero no necesariamente una precisión de nanosegundos. No hay garantías sobre la frecuencia con la que cambian los valores.

Como yo lo veo, esto puede interpretarse de dos maneras diferentes:

  1. La oración en negrita anterior se refiere a valores de retorno individuales. Entonces, la precisión y la exactitud deben entenderse en el sentido numérico. Es decir, la precisión se refiere al número de dígitos significativos: la posición del truncamiento y la precisión es si el número es el correcto (como se describe aquí en la respuesta superior, ¿cuál es la diferencia entre "precisión" y "precisión"? )

  2. La oración en negrita anterior se refiere a la capacidad del método en sí. Entonces, precisión y exactitud deben entenderse como se ilustra en la analogía de la diana ( http://en.wikipedia.org/wiki/Precision_vs._accuracy#Accuracy_versus_precision:_the_target_analogy ). Por lo tanto, baja precisión, alta precisión => el valor incorrecto se golpea repetidamente con una alta precisión: al imaginar que el tiempo físico se detiene, las llamadas consecutivas de nanoTime () devuelven el mismo valor numérico, pero están fuera del tiempo real transcurrido desde el Tiempo de referencia por alguna compensación constante .

¿Qué interpretación es la correcta? Mi punto es que la interpretación 2 significaría que una medida de la diferencia de tiempo usando nanoTime () (al restar dos valores de retorno) sería correcta al nanosegundo (ya que el error / desplazamiento constante en la medición se eliminaría), mientras que la interpretación 1 lo haría. No garantizamos ese tipo de cumplimiento entre mediciones y, por lo tanto, no implicaría necesariamente una alta precisión en las mediciones de diferencia de tiempo.

Actualizado 15/04/13: La documentación de Java 7 para System.nanoTime() se ha actualizado para solucionar la posible confusión con la redacción anterior.

Devuelve el valor actual de la fuente de tiempo de alta resolución de la máquina virtual Java en ejecución, en nanosegundos.

Este método solo se puede utilizar para medir el tiempo transcurrido y no está relacionado con ninguna otra noción del sistema o del reloj de pared. El valor devuelto representa nanosegundos desde un tiempo de origen fijo pero arbitrario (quizás en el futuro, por lo que los valores pueden ser negativos). El mismo origen es utilizado por todas las invocaciones de este método en una instancia de una máquina virtual Java; Es probable que otras instancias de máquinas virtuales utilicen un origen diferente.

Este método proporciona una precisión de nanosegundos, pero no necesariamente una resolución de nanosegundos (es decir, con qué frecuencia cambia el valor); no se ofrecen garantías, excepto que la resolución es al menos tan buena como la de currentTimeMillis() .

Las diferencias en llamadas sucesivas que abarcan más de aproximadamente 292 años (2 63 nanosegundos) no calcularán correctamente el tiempo transcurrido debido a un desbordamiento numérico.

Los valores devueltos por este método adquieren sentido solo cuando se calcula la diferencia entre dos de estos valores, obtenidos en la misma instancia de una máquina virtual Java.


En la línea de comandos de Clojure, obtengo:

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

Esencialmente, nanoTime no se actualiza cada nanosegundo, al contrario de lo que uno podría esperar intuitivamente de su precisión . En los sistemas Windows, utiliza la API QueryPerformanceCounter debajo del capó (según este artículo ), que en la práctica parece dar una resolución de aproximadamente 640 ns (¡en mi sistema!).

Tenga en cuenta que nanoTime no puede, por sí mismo, tener precisión alguna, ya que su valor absoluto es arbitrario. Sólo la diferencia entre las sucesivas llamadas de nanoTime es significativa. La (in) precisión de esa diferencia está en el campo de juego de 1 microsegundo.


La primera interpretación es correcta. En la mayoría de los sistemas, los tres dígitos menos significativos siempre serán cero. En efecto, esto proporciona una precisión de microsegundos, pero lo reporta en el nivel de precisión fijo de un nanosegundo.

De hecho, ahora que lo vuelvo a ver, su segunda interpretación también es una descripción válida de lo que está sucediendo, tal vez incluso más. Al imaginar el tiempo congelado, el informe siempre tendrá el mismo número incorrecto de nanosegundos, pero correcto si se entiende como el número entero de microsegundos.


Si alguien como yo viene y lee esta pregunta una y otra vez para seguir entendiéndolo, aquí hay una explicación más simple (espero).

Precision es sobre cuántos dígitos retienes. Cada una de las:

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

va a ser un número preciso (muchos dígitos).

Dado que la accuracy solo se mide en comparación con algo , una llamada individual a System.nanoTime no tiene sentido, ya que su valor es bastante arbitrario y no depende de algo que podamos medir. La única forma de distinguir su precisión es mediante dos llamadas diferentes, por lo tanto:

long howMuch = end - start;

No va a tener una precisión nano-segundo. Y de hecho, en mi máquina, la diferencia es de 0,2 a 0,3 microsegundos.


Una característica bastante interesante de la diferencia entre System.currentTimeMillis() y System.nanoTime() es que System.nanoTime() NO cambia con el reloj de pared. Ejecuto el código en una máquina virtual de Windows que tiene mucha tendencia a la deriva. System.currentTimeMillis() puede retroceder o avanzar 1-2 segundos cada vez que el NTP corrige esa deriva, lo que hace que las marcas de tiempo exactas no tengan sentido. (Windows 2003, ediciones VPS 2008)

System.nanoTime() embargo, System.nanoTime() no se ve afectado por el cambio del tiempo del reloj de pared, por lo que puede tomar un tiempo recuperado a través de NTP y aplicar una corrección basada en System.nanoTime() desde que se verificó el último NTP y tiene una hora mucho más precisa que System.currentTimeMillis() en condiciones adversas de reloj de pared

Esto es, por supuesto, contraintuitivo, pero útil para saberlo.