sobrecarga poo operadores metodos ejemplo constructores java timestamp overhead

poo - Tiempo de medición de sobrecarga en Java



sobrecarga en poo (7)

Al medir el tiempo transcurrido en un nivel bajo, tengo la opción de usar cualquiera de estos:

System.currentTimeMillis(); System.nanoTime();

Ambos métodos se implementan de forma native . Antes de profundizar en cualquier código C, ¿alguien sabe si hay una sobrecarga sustancial que llama a uno u otro? Quiero decir, si realmente no me importa la precisión extra, ¿cuál se esperaría que consumiera menos CPU?

NB: Estoy usando el Java 1.6 JDK estándar, pero la pregunta puede ser válida para cualquier JRE ...


A nivel teórico, para una VM que utiliza subprocesos nativos y se asienta en un moderno sistema operativo preventivo, se puede implementar currentTimeMillis para que se lea solo una vez por intervalo de tiempo. Presumiblemente, las implementaciones de nanoTime no sacrificarían la precisión.


La respuesta aceptada a esta pregunta es ciertamente incorrecta. La respuesta alternativa proporcionada por @brettw es buena, pero no obstante, es ligera en los detalles.

Para un tratamiento completo de este tema y el costo real de estas llamadas, consulte https://shipilev.net/blog/2014/nanotrusting-nanotime/

Para responder a la pregunta formulada:

¿Alguien sabe si hay una sobrecarga sustancial llamando a uno u otro?

  • La sobrecarga de llamadas a System#nanoTime es de 15 a 30 nanosegundos por llamada.
  • El valor reportado por nanoTime , su resolución, solo cambia una vez por 30 nanosegundos

Esto significa que dependiendo de si está intentando hacer millones de solicitudes por segundo, llamar a nanoTime significa que está perdiendo efectivamente una gran parte de la segunda llamada de nanoTime . Para tales casos de uso, considere cualquiera de las solicitudes de medición del lado del cliente, asegurándose de que no caiga en una omisión coordinada , la medición de la profundidad de la cola también es un buen indicador.

Si no está tratando de abarrotar tanto trabajo como pueda en un solo segundo, entonces nanoTime realmente no importará, pero la omisión coordinada sigue siendo un factor.

Finalmente, para completar, currentTimeMillis no se puede usar sin importar su costo. Esto se debe a que no está garantizado para avanzar entre dos llamadas. Especialmente en un servidor con NTP, currentTimeMillis está en constante movimiento. Sin mencionar que la mayoría de las cosas medidas por una computadora no toman un milisegundo completo.


La respuesta marcada correctamente en esta página no es correcta. Esa no es una forma válida de escribir un punto de referencia debido a la eliminación de código muerto (DCE) de la JVM, el reemplazo en la pila (OSR), el desenrollado de bucles, etc. Solo un marco como el marco de micro-benchmarking JMH de Oracle puede medir algo así correctamente. Lea esta publicación si tiene alguna duda sobre la validez de estos micro puntos de referencia.

Aquí hay un punto de referencia JMH para System.currentTimeMillis() vs System.nanoTime() :

@BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Benchmark) public class NanoBench { @Benchmark public long currentTimeMillis() { return System.currentTimeMillis(); } @Benchmark public long nanoTime() { return System.nanoTime(); } }

Y aquí están los resultados (en un Intel Core i5):

Benchmark Mode Samples Mean Mean err Units c.z.h.b.NanoBench.currentTimeMillis avgt 16 122.976 1.748 ns/op c.z.h.b.NanoBench.nanoTime avgt 16 117.948 3.075 ns/op

Lo que muestra que System.nanoTime() es ligeramente más rápido en ~ 118ns por invocación en comparación con ~ 123ns. Sin embargo, también está claro que una vez que se toma en cuenta el error medio, hay muy poca diferencia entre los dos. Los resultados también pueden variar según el sistema operativo. Pero la conclusión general debería ser que son esencialmente equivalentes en términos de gastos generales.

ACTUALIZACIÓN 2015/08/25: Aunque esta respuesta está más cerca de corregir que la mayoría, usar JMH para medir, todavía no es correcto. Medir algo como System.nanoTime() sí mismo es un tipo especial de benchmarking retorcido. La respuesta y el artículo definitivo están here .


No creo que debas preocuparte por la sobrecarga de ninguno de los dos. Es tan mínimo que apenas se puede medir. Aquí hay una rápida micro-referencia de ambos:

for (int j = 0; j < 5; j++) { long time = System.nanoTime(); for (int i = 0; i < 1000000; i++) { long x = System.currentTimeMillis(); } System.out.println((System.nanoTime() - time) + "ns per million"); time = System.nanoTime(); for (int i = 0; i < 1000000; i++) { long x = System.nanoTime(); } System.out.println((System.nanoTime() - time) + "ns per million"); System.out.println(); }

Y el último resultado:

14297079ns per million 29206842ns per million

Parece que System.currentTimeMillis() es dos veces más rápido que System.nanoTime() . Sin embargo, 29ns será mucho más corto que cualquier otra cosa que medirías de todos modos. Prefiero System.nanoTime() por precisión y exactitud, ya que no está asociado con los relojes.


Si tiene tiempo, vea esta charla de Cliff Click , él habla sobre el precio de System.currentTimeMillis , así como otras cosas.


Solo debes usar System.nanoTime() para medir el tiempo que tarda algo en ejecutarse. No es solo una cuestión de la precisión de nanosegundos, System.currentTimeMillis() es "tiempo de reloj de pared", mientras que System.nanoTime() está diseñado para sincronizar cosas y no tiene las peculiaridades del "tiempo real" que el otro tiene. Desde el Javadoc de System.nanoTime() :

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.


System.currentTimeMillis() es generalmente muy rápido (afaik 5-6 ciclos de cpu, pero no sé dónde he leído esto más), pero la resolución varía en diferentes plataformas.

Entonces, si necesita alta precisión, vaya para nanoTime() , si está preocupado por los gastos generales, vaya por currentTimeMillis() .