¿Cómo programo la ejecución de un método en Java?

834
  1. ¿Cómo obtengo el tiempo de ejecución de un método?
  2. ¿Hay una Timerclase de utilidad para cosas como el tiempo que dura una tarea, etc.?

La mayoría de las búsquedas en Google devuelven resultados de temporizadores que programan hilos y tareas, que no es lo que quiero.

Salmo de ogro33
fuente
JAMon API es una API Java gratuita, simple, de alto rendimiento y segura para subprocesos que permite a los desarrolladores monitorear fácilmente el rendimiento y la escalabilidad de las aplicaciones de producción. JAMon rastrea los éxitos, los tiempos de ejecución (total, promedio, mínimo, máximo, desarrollo estándar) y más. http://jamonapi.sourceforge.net/ descarga: http://sourceforge.net/project/showfiles.php?group_id=96550
Mike Pone
1
También es posible que desee ver la clase Apache Commons Lang StopWatch . Una clase de utilidad simple pero útil.
Pregunta similar posterior: ¿Cómo escribo un micro benchmark correcto en Java?
Basil Bourque
Sí, StopWatch es genial para esto.
Shubham Pandey
Java 8 usando la Instantclase: stackoverflow.com/a/30975902/1216775
akhil_mittal

Respuestas:

1208

Siempre hay una forma anticuada:

long startTime = System.nanoTime();
methodToTime();
long endTime = System.nanoTime();

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
Diastrofismo
fuente
234
en realidad, es "nuevo" porque usaste nanoTime, que no se agregó hasta java5
John Gardner
11
Esto (o usar System.currentTimeMillis ()) parece ser la forma en que generalmente se hace en Java ... que he visto de todos modos. Todavía me sorprende un poco que no haya una clase incorporada elegante, como Timer t = new Timer (); Cadena s = t.getElapsed (formato); etc ...
Ogre Psalm33
18
nanoTime no garantiza una precisión mejor que currentTimeMillis (), aunque generalmente lo hace. forums.sun.com/thread.jspa?messageID=9460663 y simongbrown.com/blog/2007/08/20/…
James Schek
10
Por supuesto, siempre es importante recordar las trampas de optimizaciones micro-evaluación comparativa, como compilador / JVM que pueden distorsionar el resultado = 8-)
Yuval
18
No hay necesidad de un bloqueo final ya que endTime no se usará si se lanza una excepción.
Peter Lawrey
197

Voy con la respuesta simple. Funciona para mi.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

System.out.println("That took " + (endTime - startTime) + " milliseconds");

Funciona bastante bien La resolución obviamente es solo de milisegundos, puede mejorar con System.nanoTime (). Existen algunas limitaciones para ambos (segmentos de programación del sistema operativo, etc.) pero esto funciona bastante bien.

Promedio en un par de carreras (cuanto más, mejor) y obtendrá una idea decente.

MBCook
fuente
51
En realidad, System.currentTimeMillis () solo tiene una precisión superior a 15 ms. Para valores realmente bajos no se puede confiar. La solución para esto (como se mencionó) es System.nanoTime ();
Steve g
Ok, estaba a punto de aceptar esto como la respuesta oficial hasta que leí el comentario de Steve G. Gran noticia, Steve!
Ogre Psalm33
44
nanoTime () no garantiza una precisión mejor que currentTimeMillis, pero muchas implementaciones de JVM tienen una mejor precisión con nanoTime.
James Schek
55
@JamesSchek Realmente necesitas ver tu redacción, como ya mencioné en este comentario idéntico en otra parte; nanoTimese garantiza que sea al menos tan resuelto como currentTimeMillis. docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy
La única pequeña ventaja currentTimeMillises que es una marca de tiempo real, y también podría usarse para registrar las horas de inicio / finalización, mientras que nanoTime"solo se puede usar para medir el tiempo transcurrido y no está relacionado con ninguna otra noción de tiempo de sistema o reloj de pared". ".
Brad Parks el
177

¡Vamos chicos! Nadie mencionó la forma en que Guava hace eso (lo cual es posiblemente increíble):

import com.google.common.base.Stopwatch;

Stopwatch timer = Stopwatch.createStarted();
//method invocation
LOG.info("Method took: " + timer.stop());

Lo bueno es que Stopwatch.toString () hace un buen trabajo al seleccionar unidades de tiempo para la medición. Es decir, si el valor es pequeño, generará 38 ns, si es largo, mostrará 5m 3s

Aún mejor:

Stopwatch timer = Stopwatch.createUnstarted();
for (...) {
   timer.start();
   methodToTrackTimeFor();
   timer.stop();
   methodNotToTrackTimeFor();
}
LOG.info("Method took: " + timer);

Nota: Google Guava requiere Java 1.6+

Dmitry Kalashnikov
fuente
21
Desafortunadamente, Guava's Stopwatch no es seguro para subprocesos. Aprendí esto de la manera difícil.
Dexter Legaspi
66
@DexterLegaspi ¡Estaría muy interesado en su experiencia! ¿Quieres compartir?
Siddhartha
1
El uso del cronómetro en paralelo lo llevaría a llamar start()varias veces seguidas (lo mismo para stop()).
Mingwei Samuel
141

Usando Instant y Duration de la nueva API de Java 8,

Instant start = Instant.now();
Thread.sleep(5000);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

salidas,

PT5S
Sufiyan Ghori
fuente
2
Gracias, ¿cómo puedo generar el resultado sin tener el PT delante?
java123999
1
El problema con el método es que Instant no tiene problemas con la precisión de milisegundos y nano segundos. Ref: stackoverflow.com/questions/20689055/…
prashantsunkari
8
@ java123999: puedes llamar Duration.between(start, end).getSeconds(). Durationtambién tiene métodos para convertir a otras unidades de tiempo, por ejemplo, toMillis()que convierte a milisegundos.
Emil Lunde
100

Reunió todas las formas posibles juntas en un solo lugar.

Fecha

Date startDate = Calendar.getInstance().getTime();
long d_StartTime = new Date().getTime();
Thread.sleep(1000 * 4);
Date endDate = Calendar.getInstance().getTime();
long d_endTime = new Date().getTime();
System.out.format("StartDate : %s, EndDate : %s \n", startDate, endDate);
System.out.format("Milli = %s, ( D_Start : %s, D_End : %s ) \n", (d_endTime - d_StartTime),d_StartTime, d_endTime);

Sistema. currentTimeMillis ()

long startTime = System.currentTimeMillis();
Thread.sleep(1000 * 4);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);  
System.out.format("Milli = %s, ( S_Start : %s, S_End : %s ) \n", duration, startTime, endTime );
System.out.println("Human-Readable format : "+millisToShortDHMS( duration ) );

Formato legible para humanos

public static String millisToShortDHMS(long duration) {
    String res = "";    // java.util.concurrent.TimeUnit;
    long days       = TimeUnit.MILLISECONDS.toDays(duration);
    long hours      = TimeUnit.MILLISECONDS.toHours(duration) -
                      TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes    = TimeUnit.MILLISECONDS.toMinutes(duration) -
                      TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds    = TimeUnit.MILLISECONDS.toSeconds(duration) -
                      TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    long millis     = TimeUnit.MILLISECONDS.toMillis(duration) - 
                      TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration));

    if (days == 0)      res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis);
    else                res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis);
    return res;
}

Guayaba: Google Stopwatch JAR «Un objeto de Stopwatch es medir el tiempo transcurrido en nanosegundos.

com.google.common.base.Stopwatch g_SW = Stopwatch.createUnstarted();
g_SW.start();
Thread.sleep(1000 * 4);
g_SW.stop();
System.out.println("Google StopWatch  : "+g_SW);

Apache Commons Lang JAR « StopWatch proporciona una API conveniente para los tiempos.

org.apache.commons.lang3.time.StopWatch sw = new StopWatch();
sw.start();     
Thread.sleep(1000 * 4);     
sw.stop();
System.out.println("Apache StopWatch  : "+ millisToShortDHMS(sw.getTime()) );

JODA TIEMPO

public static void jodaTime() throws InterruptedException, ParseException{
    java.text.SimpleDateFormat ms_SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
    String start = ms_SDF.format( new Date() ); // java.util.Date

    Thread.sleep(10000);

    String end = ms_SDF.format( new Date() );       
    System.out.println("Start:"+start+"\t Stop:"+end);

    Date date_1 = ms_SDF.parse(start);
    Date date_2 = ms_SDF.parse(end);        
    Interval interval = new org.joda.time.Interval( date_1.getTime(), date_2.getTime() );
    Period period = interval.toPeriod(); //org.joda.time.Period

    System.out.format("%dY/%dM/%dD, %02d:%02d:%02d.%04d \n", 
        period.getYears(), period.getMonths(), period.getDays(),
        period.getHours(), period.getMinutes(), period.getSeconds(), period.getMillis());
}

API de fecha y hora de Java de Java 8 «Un objeto de duración representa un período de tiempo entre dos objetos instantáneos .

Instant start = java.time.Instant.now();
    Thread.sleep(1000);
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.println( between ); // PT1.001S
System.out.format("%dD, %02d:%02d:%02d.%04d \n", between.toDays(),
        between.toHours(), between.toMinutes(), between.getSeconds(), between.toMillis()); // 0D, 00:00:01.1001 

Spring Framework proporcionala clase de utilidad StopWatch para medir el tiempo transcurrido en Java.

StopWatch sw = new org.springframework.util.StopWatch();
sw.start("Method-1"); // Start a named task
    Thread.sleep(500);
sw.stop();

sw.start("Method-2");
    Thread.sleep(300);
sw.stop();

sw.start("Method-3");
    Thread.sleep(200);
sw.stop();

System.out.println("Total time in milliseconds for all tasks :\n"+sw.getTotalTimeMillis());
System.out.println("Table describing all tasks performed :\n"+sw.prettyPrint());

System.out.format("Time taken by the last task : [%s]:[%d]", 
        sw.getLastTaskName(),sw.getLastTaskTimeMillis());

System.out.println("\n Array of the data for tasks performed « Task Name: Time Taken");
TaskInfo[] listofTasks = sw.getTaskInfo();
for (TaskInfo task : listofTasks) {
    System.out.format("[%s]:[%d]\n", 
            task.getTaskName(), task.getTimeMillis());
}

Salida:

Total time in milliseconds for all tasks :
999
Table describing all tasks performed :
StopWatch '': running time (millis) = 999
-----------------------------------------
ms     %     Task name
-----------------------------------------
00500  050%  Method-1
00299  030%  Method-2
00200  020%  Method-3

Time taken by the last task : [Method-3]:[200]
 Array of the data for tasks performed « Task Name: Time Taken
[Method-1]:[500]
[Method-2]:[299]
[Method-3]:[200]
Yash
fuente
El cronómetro de Guava, Apache Commons y Spring Framework no son seguros para subprocesos. No es seguro para el uso de producción.
Deepak Puthraya
@DeepakPuthraya, entonces, ¿qué biblioteca usar y cuál es segura para el uso de producción?
gaurav
1
@DeepakPuthraya puede usar la API Java Java de fecha y hora proporcionada por Java 8. Lo cual es simple.
Yash
OMI esta publicación se beneficiaría si todas las soluciones también mostraran la salida de las salidas del sistema.
BAERUS
87

Utilice un generador de perfiles (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler, etc.). Obtendrá los resultados más precisos y es el menos intrusivo. Utilizan el mecanismo JVM incorporado para la creación de perfiles, que también puede proporcionarle información adicional como seguimientos de pila, rutas de ejecución y resultados más completos si es necesario.

Cuando se utiliza un generador de perfiles totalmente integrado, es muy trivial perfilar un método. Haga clic derecho, Profiler -> Agregar a métodos de raíz. Luego ejecute el generador de perfiles como si estuviera haciendo una ejecución de prueba o depurador.

James Schek
fuente
Esta fue también una gran sugerencia, y uno de esos momentos "duh" de bombilla para mí cuando leí esta respuesta. Nuestro proyecto usa JDeveloper, pero lo comprobé, y efectivamente, ¡tiene un generador de perfiles incorporado!
Ogre Psalm33
2
Desde java 7 build 40 (creo) incluyeron el antiguo JRockits Flight Recorder a java (búsqueda de Java Mission Control)
Niels Bech Nielsen
Efectivamente @NielsBechNielsen! oracle.com/technetwork/java/javaseproducts/mission-control/…
Ogre Psalm33
¿Cómo obtener la ejecución del método en Java por Visual VM, por ejemplo?
okwap
41

Probablemente esto no sea lo que querías que dijera, pero este es un buen uso de AOP. Agite un interceptor proxy alrededor de su método y realice el cronometraje allí.

Lamentablemente, el qué, el por qué y el cómo de AOP está más allá del alcance de esta respuesta, pero así es como probablemente lo haría.

Editar: aquí hay un enlace a Spring AOP para comenzar, si está interesado. Esta es la implementación más accesible de AOP que he encontrado para Java.

Además, dadas las sugerencias muy simples de todos los demás, debo agregar que AOP es para cuando no quieres que cosas como el tiempo invadan tu código. Pero en muchos casos, ese tipo de enfoque simple y fácil está bien.

skaffman
fuente
3
Aquí hay un tutorial sobre cómo hacer esto con Spring: veerasundar.com/blog/2010/01/…
David Tinker
39

System.currentTimeMillis();NO ES un buen enfoque para medir el rendimiento de sus algoritmos. Mide el tiempo total que experimenta como usuario mirando la pantalla de la computadora. También incluye el tiempo consumido por todo lo demás que se ejecuta en segundo plano en su computadora. Esto podría marcar una gran diferencia en caso de que tenga muchos programas ejecutándose en su estación de trabajo.

Enfoque adecuado está utilizando java.lang.managementpaquete.

Del sitio web http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking :

  • El "tiempo de usuario" es el tiempo dedicado a ejecutar el código propio de su aplicación.
  • El "tiempo del sistema" es el tiempo dedicado a ejecutar el código del sistema operativo en nombre de su aplicación (como por ejemplo, para E / S).

getCpuTime() El método te da la suma de esos:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;

public class CPUUtils {

    /** Get CPU time in nanoseconds. */
    public static long getCpuTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadCpuTime( ) : 0L;
    }

    /** Get user time in nanoseconds. */
    public static long getUserTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadUserTime( ) : 0L;
    }

    /** Get system time in nanoseconds. */
    public static long getSystemTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            (bean.getCurrentThreadCpuTime( ) - bean.getCurrentThreadUserTime( )) : 0L;
    }

}
TondaCZE
fuente
44
Este es definitivamente un buen punto, que el "tiempo de usuario" (tiempo de reloj de pared) no siempre es una gran medida de rendimiento, especialmente en un programa de subprocesos múltiples.
Ogre Psalm33
Esta es la respuesta que estoy buscando.
ZhaoGang
30

Con Java 8 también puede hacer algo como esto con todos los métodos normales :

Object returnValue = TimeIt.printTime(() -> methodeWithReturnValue());
//do stuff with your returnValue

con TimeIt like:

public class TimeIt {

public static <T> T printTime(Callable<T> task) {
    T call = null;
    try {
        long startTime = System.currentTimeMillis();
        call = task.call();
        System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");
    } catch (Exception e) {
        //...
    }
    return call;
}
}

Con este método, puede realizar mediciones de tiempo fáciles en cualquier parte de su código sin romperlo. En este sencillo ejemplo, solo imprimo la hora. Puede agregar un Switch para TimeIt, por ejemplo, para imprimir solo la hora en DebugMode o algo así.

Si está trabajando con Function , puede hacer algo como esto:

Function<Integer, Integer> yourFunction= (n) -> {
        return IntStream.range(0, n).reduce(0, (a, b) -> a + b);
    };

Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);
//do stuff with your returnValue

public static <T, R> Function<T, R> printTime2(Function<T, R> task) {
    return (t) -> {
        long startTime = System.currentTimeMillis();
        R apply = task.apply(t);
        System.out.print((System.currentTimeMillis() - startTime) / 1000d
                + "s");
        return apply;
    };
}
Stefan
fuente
Esto se ve mucho mejor que otras soluciones. Está más cerca de Spring AOP pero más ligero que eso. Verdadero java 8 way! +1 ¡Gracias!
Amit Kumar
Tal vez esto te parezca bien, porque Stefan está utilizando nuevas y elegantes funciones de Java. Pero creo que esto es innecesariamente difícil de leer y entender.
Stimpson Cat
18

También podemos usar la clase StopWatch de comunes de Apache para medir el tiempo.

Código de muestra

org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();

System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());
sw.start();

// Method execution code

sw.stop();
System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());
Narayan
fuente
15

Solo un pequeño giro, si no usa herramientas y desea cronometrar métodos con un tiempo de ejecución bajo: ejecútelo muchas veces, duplicando cada vez el número de veces que se ejecuta hasta llegar a un segundo, más o menos. Por lo tanto, el tiempo de la Llamada a System.nanoTime y demás, ni la precisión de System.nanoTime afectan mucho el resultado.

    int runs = 0, runsPerRound = 10;
    long begin = System.nanoTime(), end;
    do {
        for (int i=0; i<runsPerRound; ++i) timedMethod();
        end = System.nanoTime();
        runs += runsPerRound;
        runsPerRound *= 2;
    } while (runs < Integer.MAX_VALUE / 2 && 1000000000L > end - begin);
    System.out.println("Time for timedMethod() is " + 
        0.000000001 * (end-begin) / runs + " seconds");

Por supuesto, se aplican las advertencias sobre el uso del reloj de pared: influencias de la compilación JIT, múltiples subprocesos / procesos, etc. Por lo tanto, primero debe ejecutar el método muchas veces primero, de modo que el compilador JIT haga su trabajo, y luego repita esta prueba varias veces y tome el tiempo de ejecución más bajo.

Hans-Peter Störr
fuente
13

Estamos utilizando las anotaciones de AspectJ y Java para este propósito. Si necesitamos saber el tiempo de ejecución de un método, simplemente lo anotamos. Una versión más avanzada podría usar un nivel de registro propio que se puede habilitar y deshabilitar en tiempo de ejecución.

public @interface Trace {
  boolean showParameters();
}

@Aspect
public class TraceAspect {
  [...]
  @Around("tracePointcut() && @annotation(trace) && !within(TraceAspect)")
  public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {

    Object result;
    // initilize timer

    try { 
      result = jp.procced();
    } finally { 
      // calculate execution time 
    }

    return result;
  }
  [...]
}

fuente
13

JEP 230: Suite Microbenchmark

FYI, JEP 230: Microbenchmark Suite es un proyecto OpenJDK para:

Agregue un conjunto básico de microbenchmarks al código fuente JDK y facilite a los desarrolladores ejecutar microbenchmarks existentes y crear otros nuevos.

Esta característica llegó a Java 12 .

Arnés de microbenchmark de Java (JMH)

Para versiones anteriores de Java, eche un vistazo al proyecto de Java Microbenchmark Harness (JMH) en el que se basa JEP 230.

Albahaca Bourque
fuente
11

Muy buen código.

http://www.rgagnon.com/javadetails/java-0585.html

import java.util.concurrent.TimeUnit;

long startTime = System.currentTimeMillis();
........
........
........
long finishTime = System.currentTimeMillis();

String diff = millisToShortDHMS(finishTime - startTime);


  /**
   * converts time (in milliseconds) to human-readable format
   *  "<dd:>hh:mm:ss"
   */
  public static String millisToShortDHMS(long duration) {
    String res = "";
    long days  = TimeUnit.MILLISECONDS.toDays(duration);
    long hours = TimeUnit.MILLISECONDS.toHours(duration)
                   - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
                     - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
                   - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    if (days == 0) {
      res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
    else {
      res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
    }
    return res;
  }
iceberg
fuente
3
En realidad, la pregunta era cómo calcular la cantidad de tiempo que tarda un método, no cómo formatearlo. Sin embargo, esta pregunta es bastante antigua (¡casi cuatro años!). Intente evitar resucitar hilos viejos a menos que la respuesta agregue algo nuevo y significativo sobre las respuestas existentes.
Leigh
1
Y para agregar los milis restantes hasta el final, realice los siguientes cambios: long millis = TimeUnit.MILLISECONDS.toMillis(duration) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration)); if (days == 0) { res = String.format("%02d:%02d:%02d.%02d", hours, minutes, seconds, millis); } else { res = String.format("%dd%02d:%02d:%02d.%02d", days, hours, minutes, seconds, millis); }
Rick Barkhouse el
10

Puedes usar Perf4j . Muy buena utilidad. El uso es simple

String watchTag = "target.SomeMethod";
StopWatch stopWatch = new LoggingStopWatch(watchTag);
Result result = null; // Result is a type of a return value of a method
try {
    result = target.SomeMethod();
    stopWatch.stop(watchTag + ".success");
} catch (Exception e) {
    stopWatch.stop(watchTag + ".fail", "Exception was " + e);
    throw e; 
}

Se puede encontrar más información en la Guía del desarrollador

Editar: Proyecto parece muerto

mergenchik
fuente
1
Perf4j también puede generar buenas estadísticas .
Paaske
8
new Timer(""){{
    // code to time 
}}.timeMe();



public class Timer {

    private final String timerName;
    private long started;

    public Timer(String timerName) {
        this.timerName = timerName;
        this.started = System.currentTimeMillis();
    }

    public void timeMe() {
        System.out.println(
        String.format("Execution of '%s' takes %dms.", 
                timerName, 
                started-System.currentTimeMillis()));
    }

}
Maciek Kreft
fuente
1
Lanzar su propia clase simple es una buena opción cuando ya tiene configurado el sistema de compilación y el OTS dependiente, y no desea molestarse en obtener otro paquete OTS que incluya una clase de temporizador de utilidad.
Ogre Psalm33
7

Básicamente, hago variaciones de esto, pero teniendo en cuenta cómo funciona la compilación de puntos de acceso, si desea obtener resultados precisos, debe descartar las primeras mediciones y asegurarse de que está utilizando el método en una aplicación del mundo real (leer la aplicación específica).

Si el JIT decide compilarlo, sus números variarán mucho. así que solo ten en cuenta

luke
fuente
7

Usando AOP / AspectJ y @Loggableanotaciones de jcabi-Aspect puede hacerlo de manera fácil y compacta:

@Loggable(Loggable.DEBUG)
public String getSomeResult() {
  // return some value
}

Cada llamada a este método se enviará a la instalación de registro SLF4J con DEBUGnivel de registro. Y cada mensaje de registro incluirá el tiempo de ejecución.

yegor256
fuente
7

Spring proporciona una clase de utilidad org.springframework.util.StopWatch , según JavaDoc:

Cronómetro simple, que permite el tiempo de una serie de tareas, exponiendo el tiempo total de ejecución y el tiempo de ejecución para cada tarea nombrada.

Uso:

StopWatch stopWatch = new StopWatch("Performance Test Result");

stopWatch.start("Method 1");
doSomething1();//method to test
stopWatch.stop();

stopWatch.start("Method 2");
doSomething2();//method to test
stopWatch.stop();

System.out.println(stopWatch.prettyPrint());

Salida:

StopWatch 'Performance Test Result': running time (millis) = 12829
-----------------------------------------
ms     %     Task name
-----------------------------------------
11907  036%  Method 1
00922  064%  Method 2

Con aspectos:

@Around("execution(* my.package..*.*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    Object retVal = joinPoint.proceed();
    stopWatch.stop();
    log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");
    return retVal;
}
Sunil Manheri
fuente
¿Es posible usar esto con AspectJ?
zygimantus
7

He escrito un método para imprimir el tiempo de ejecución del método en una forma muy legible. Por ejemplo, para calcular el factorial de 1 millón, se tarda aproximadamente 9 minutos. Entonces el tiempo de ejecución se imprime como:

Execution Time: 9 Minutes, 36 Seconds, 237 MicroSeconds, 806193 NanoSeconds

El código está aquí:

public class series
{
    public static void main(String[] args)
    {
        long startTime = System.nanoTime();

        long n = 10_00_000;
        printFactorial(n);

        long endTime = System.nanoTime();
        printExecutionTime(startTime, endTime);

    }

    public static void printExecutionTime(long startTime, long endTime)
    {
        long time_ns = endTime - startTime;
        long time_ms = TimeUnit.NANOSECONDS.toMillis(time_ns);
        long time_sec = TimeUnit.NANOSECONDS.toSeconds(time_ns);
        long time_min = TimeUnit.NANOSECONDS.toMinutes(time_ns);
        long time_hour = TimeUnit.NANOSECONDS.toHours(time_ns);

        System.out.print("\nExecution Time: ");
        if(time_hour > 0)
            System.out.print(time_hour + " Hours, ");
        if(time_min > 0)
            System.out.print(time_min % 60 + " Minutes, ");
        if(time_sec > 0)
            System.out.print(time_sec % 60 + " Seconds, ");
        if(time_ms > 0)
            System.out.print(time_ms % 1E+3 + " MicroSeconds, ");
        if(time_ns > 0)
            System.out.print(time_ns % 1E+6 + " NanoSeconds");
    }
}
Pratik Patil
fuente
6

Hay un par de formas de hacerlo. Normalmente vuelvo a usar algo como esto:

long start = System.currentTimeMillis();
// ... do something ...
long end = System.currentTimeMillis();

o lo mismo con System.nanoTime ();

Para algo más en el lado de la evaluación comparativa de las cosas también parece ser este: http://jetm.void.fm/ Sin embargo, nunca lo intenté.

Horst Gutmann
fuente
6

Puede usar la biblioteca de métricas que proporciona varios instrumentos de medición. Añadir dependencia:

<dependencies>
    <dependency>
        <groupId>io.dropwizard.metrics</groupId>
        <artifactId>metrics-core</artifactId>
        <version>${metrics.version}</version>
    </dependency>
</dependencies>

Y configúrelo para su entorno.

Los métodos se pueden anotar con @Timed :

@Timed
public void exampleMethod(){
    // some code
}

o pieza de código envuelta con Timer :

final Timer timer = metricsRegistry.timer("some_name");
final Timer.Context context = timer.time();
// timed code
context.stop();

Las métricas agregadas se pueden exportar a la consola, JMX, CSV u otras.

@Timed ejemplo de salida de métricas:

com.example.ExampleService.exampleMethod
             count = 2
         mean rate = 3.11 calls/minute
     1-minute rate = 0.96 calls/minute
     5-minute rate = 0.20 calls/minute
    15-minute rate = 0.07 calls/minute
               min = 17.01 milliseconds
               max = 1006.68 milliseconds
              mean = 511.84 milliseconds
            stddev = 699.80 milliseconds
            median = 511.84 milliseconds
              75% <= 1006.68 milliseconds
              95% <= 1006.68 milliseconds
              98% <= 1006.68 milliseconds
              99% <= 1006.68 milliseconds
            99.9% <= 1006.68 milliseconds
Tal como
fuente
5

Si quieres tiempo de reloj de pared

long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;
David Nehme
fuente
5

Como dijo "skaffman", use AOP O puede usar el tejido de código de bytes de tiempo de ejecución, al igual que las herramientas de cobertura de métodos de prueba de unidad usan para agregar de manera transparente información de temporización a los métodos invocados.

Puede consultar el código utilizado por las herramientas de herramientas de código abierto como Emma ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ). La otra herramienta de cobertura de código abierto es http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download .

Si finalmente logra hacer lo que se propuso, por favor. compártelo de nuevo con la comunidad aquí con su tarea / jarras de hormigas.

anjanb
fuente
4
long startTime = System.currentTimeMillis();
// code goes here
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime; // elapsed time in milliseconds
Ryan Rodemoyer
fuente
4

Modifiqué el código de la respuesta correcta para obtener el resultado en segundos:

long startTime = System.nanoTime();

methodCode ...

long endTime = System.nanoTime();
double duration = (double)(endTime - startTime) / (Math.pow(10, 9));
Log.v(TAG, "MethodName time (s) = " + duration);
Denis Kutlubaev
fuente
4

Puede usar la clase de cronómetro del proyecto principal de primavera:

Código:

StopWatch stopWatch = new StopWatch()
stopWatch.start();  //start stopwatch
// write your function or line of code.
stopWatch.stop();  //stop stopwatch
stopWatch.getTotalTimeMillis() ; ///get total time

Documentación para el cronómetro: cronómetro simple, que permite la sincronización de una serie de tareas, exponiendo el tiempo total de ejecución y el tiempo de ejecución para cada tarea nombrada. Oculta el uso de System.currentTimeMillis (), lo que mejora la legibilidad del código de la aplicación y reduce la probabilidad de errores de cálculo. Tenga en cuenta que este objeto no está diseñado para ser seguro para subprocesos y no utiliza sincronización. Esta clase se usa normalmente para verificar el rendimiento durante la prueba de conceptos y en el desarrollo, en lugar de como parte de las aplicaciones de producción.

Praveen Jain
fuente
3

Puedes intentarlo de esta manera si solo quieres saber la hora.

long startTime = System.currentTimeMillis();
//@ Method call
System.out.println("Total time [ms]: " + (System.currentTimeMillis() - startTime));    
gifpif
fuente
3

Ok, esta es una clase simple que se utilizará para una sincronización simple y simple de sus funciones. Hay un ejemplo debajo de él.

public class Stopwatch {
    static long startTime;
    static long splitTime;
    static long endTime;

    public Stopwatch() {
        start();
    }

    public void start() {
        startTime = System.currentTimeMillis();
        splitTime = System.currentTimeMillis();
        endTime = System.currentTimeMillis();
    }

    public void split() {
        split("");
    }

    public void split(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Split time for [" + tag + "]: " + (endTime - splitTime) + " ms");
        splitTime = endTime;
    }

    public void end() {
        end("");
    }
    public void end(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Final time for [" + tag + "]: " + (endTime - startTime) + " ms");
    }
}

Muestra de uso:

public static Schedule getSchedule(Activity activity_context) {
        String scheduleJson = null;
        Schedule schedule = null;
/*->*/  Stopwatch stopwatch = new Stopwatch();

        InputStream scheduleJsonInputStream = activity_context.getResources().openRawResource(R.raw.skating_times);
/*->*/  stopwatch.split("open raw resource");

        scheduleJson = FileToString.convertStreamToString(scheduleJsonInputStream);
/*->*/  stopwatch.split("file to string");

        schedule = new Gson().fromJson(scheduleJson, Schedule.class);
/*->*/  stopwatch.split("parse Json");
/*->*/  stopwatch.end("Method getSchedule"); 
    return schedule;
}

Muestra de salida de consola:

Split time for [file to string]: 672 ms
Split time for [parse Json]: 893 ms
Final time for [get Schedule]: 1565 ms
msysmilu
fuente
3

En Java 8 Instantse introduce una nueva clase llamada . Según el documento:

Instant representa el comienzo de un nanosegundo en la línea de tiempo. Esta clase es útil para generar una marca de tiempo para representar el tiempo de la máquina. El rango de un instante requiere el almacenamiento de un número mayor que un largo. Para lograr esto, la clase almacena un largo que representa una época de segundos y un int que representa nanosegundos de segundo, que siempre estará entre 0 y 999,999,999. Los segundos de la época se miden a partir de la época estándar de Java de 1970-01-01T00: 00: 00Z donde los instantes después de la época tienen valores positivos y los instantes anteriores tienen valores negativos. Tanto para las partes de la época del segundo como del nanosegundo, un valor mayor siempre es posterior en la línea de tiempo que un valor menor.

Esto se puede usar como:

Instant start = Instant.now();
try {
    Thread.sleep(7000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

Se imprime PT7.001S.

akhil_mittal
fuente