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


¿Cómo obtengo el tiempo de ejecución de un método? ¿Existe una clase de utilidad Timer para cosas como calcular el tiempo que tarda una tarea, etc.?

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


661
2017-10-07 20:10


origen


Respuestas:


Siempre está la manera antigua:

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

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.

954
2017-10-07 20:16



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 es obviamente solo al milisegundo, puede hacerlo mejor con System.nanoTime (). Existen algunas limitaciones para ambos (cortes de programación del sistema operativo, etc.) pero esto funciona bastante bien.

Promedio en un par de carreras (cuantos más mejor) y obtendrá una buena idea.


160
2017-10-07 20:14



¡Vamos chicos! Nadie mencionó el Guayaba forma de hacer eso (que es posiblemente asombroso):

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 seleccionando unidades de tiempo para la medición. Es decir. si el valor es pequeño, arrojará 38 ns, si es largo, mostrará 5 m 3

Aún más agradable:

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

Nota: Google Guava requiere Java 1.6+


142
2018-03-13 20:11



Utilizando Instante y Duración 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

95
2018-02-02 09:19



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

Cuando se utiliza un perfilador totalmente integrado, es muy trivial perfilar un método. Haga clic derecho, Profiler -> Agregar a métodos de raíz. A continuación, ejecute el generador de perfiles tal como lo hacía con una ejecución de prueba o un depurador.


77
2017-10-07 21:35



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 ) );

Lectura humana Formato

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;
}

Guava: Google  CronógrafoTARRO «Un objeto de Cronómetro 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 LangTARRO  « Cronógrafo 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-HORA

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 Java date time de Java 8 " UN Duración objeto representa un período de tiempo entre dos Instante objetos.

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 

Marco de primavera proporciona Cronógrafo clase de utilidad 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]

51
2017-12-04 10:43



Probablemente esto no sea lo que querías que dijera, pero este es un buen uso de AOP. Utiliza un interceptor proxy alrededor de tu método, y haz el tiempo allí.

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

Editar: Aquí hay un enlace a Spring AOP para que comiences, si estás interesado. Esta es la implementación más accesible de AOP que Iive se encuentra para java.

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


35
2017-10-07 20:13



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

El enfoque correcto es usar java.lang.management paquete.

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

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

getCpuTime() método le da la suma de aquellos:

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;
    }

}

33
2018-04-06 13:46



Con Java 8 puedes hacer algo como esto con cada normal métodos:

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

con TimeIt gusta:

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 hacer que medir el tiempo sea fácil en cualquier parte de su código sin romperlo. En este simple ejemplo, simplemente imprimo la hora. Puede agregar un Switch para TimeIt, p. para imprimir solo la hora en DebugMode o algo así.

Si estás trabajando con Función puedes 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;
    };
}

20
2017-11-25 22:47