Como cronometro a execução de um método em Java?

834
  1. Como obtenho o tempo de execução de um método?
  2. Existe uma Timerclasse de utilidade para coisas como tempo quanto tempo uma tarefa leva, etc?

A maioria das pesquisas no Google retorna resultados para temporizadores que agendam threads e tarefas, o que não é o que eu quero.

Salmo Ogro33
fonte
A API JAMon é uma API Java gratuita, simples, de alto desempenho e com segurança para threads, que permite aos desenvolvedores monitorar facilmente o desempenho e a escalabilidade dos aplicativos de produção. O JAMon rastreia hits, tempos de execução (total, média, min, max, std dev) e muito mais. http://jamonapi.sourceforge.net/ download: http://sourceforge.net/project/showfiles.php?group_id=96550
Mike Pone
1
Você também pode consultar a classe Apache Commons Lang StopWatch . Uma classe de utilitário simples, mas útil.
Mais tarde, pergunta semelhante: Como escrevo um micro-benchmark correto em Java?
Basil Bourque
Sim, o StopWatch é ótimo para isso.
Shubham Pandey
Java 8 usando a Instantclasse: stackoverflow.com/a/30975902/1216775
akhil_mittal

Respostas:

1207

Sempre existe a maneira antiquada:

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

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
Diastrofismo
fonte
233
na verdade, a sua "nova moda" porque você usou nanoTime, o que não foi adicionado até java5
John Gardner
11
Isso (ou usando System.currentTimeMillis ()) parece ser da maneira que geralmente é feito em Java ... que eu já vi de qualquer maneira. Ainda me surpreende um pouco que não exista classe embutida, como Timer t = new Timer (); String s = t.getElapsed (formato); etc ...
Ogre Psalm33 / 08/08
18
O nanoTime não garante precisão melhor que o currentTimeMillis (), embora normalmente o faça. forums.sun.com/thread.jspa?messageID=9460663 e simongbrown.com/blog/2007/08/20/…
James Schek
10
Claro, é sempre importante lembrar as armadilhas de, como compilador de aferição micro otimizações / JVM que pode distorcer o resultado = 8-)
Yuval
18
Não há necessidade de um bloco final, pois endTime não será usado se uma exceção for lançada.
Peter Lawrey 05/05
197

Eu vou com a resposta simples. Funciona para mim.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

Funciona muito bem. Obviamente, a resolução é de apenas milissegundos; você pode fazer melhor com System.nanoTime (). Existem algumas limitações para ambos (fatias de agendamento do sistema operacional, etc.), mas isso funciona muito bem.

Média em algumas corridas (quanto mais, melhor) e você terá uma idéia decente.

MBCook
fonte
51
Na verdade, System.currentTimeMillis () é preciso apenas acima de 15ms. Para valores realmente baixos, não se pode confiar. A solução para isso (como mencionado) é System.nanoTime ();
585 Steve Steve g
Ok, eu estava prestes a aceitar isso como a resposta oficial até ler o comentário de Steve g. Que bom, Steve!
Ogre Psalm33
4
O nanoTime () não garante precisão melhor que o currentTimeMillis, mas muitas implementações da JVM têm melhor precisão com o nanoTime.
James Schek 8/10/08
5
@JamesSchek Você realmente precisa assistir sua redação, como eu já mencionei nesse comentário idêntico em outro lugar; nanoTimeé garantido que seja pelo menos tão resoluto quanto currentTimeMillis. docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy
A única vantagem currentTimeMillisdisso é que é um carimbo de data / hora real e pode ser usado para registrar também os horários de início / término, enquanto nanoTime"só pode ser usado para medir o tempo decorrido e não está relacionado a nenhuma outra noção de sistema ou hora do relógio de parede . "
Brad Parks
177

Vamos lá pessoal! Ninguém mencionou a maneira Guava de fazer isso (o que é sem dúvida incrível):

import com.google.common.base.Stopwatch;

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

O bom é que Stopwatch.toString () faz um bom trabalho ao selecionar unidades de tempo para a medição. Ou seja, se o valor for pequeno, ele produzirá 38 ns, se for longo, mostrará 5m 3s

Ainda melhor:

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

Nota: O Google Guava requer Java 1.6 ou superior

Dmitry Kalashnikov
fonte
21
Infelizmente, o cronômetro da Guava não é seguro para threads. eu aprendi isso da maneira mais difícil.
Dexter Legaspi
6
@DexterLegaspi Ficaria muito interessado em sua experiência! Cuidado em compartilhar?
Siddhartha
1
Usar o cronômetro em paralelo levaria você a ligar start()várias vezes seguidas (o mesmo para stop()).
Mingwei Samuel
141

Usando o Instant and Duration da nova API do Java 8,

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

saídas,

PT5S
Sufiyan Ghori
fonte
2
Obrigado, como posso produzir o resultado sem ter o PT na frente?
java123999
1
O problema com o método é que o Instant não causa mili e nano segundos de precisão. Ref: stackoverflow.com/questions/20689055/...
prashantsunkari
8
@ java123999: Você pode ligar Duration.between(start, end).getSeconds(). Durationtambém possui métodos para converter para outras unidades de tempo, por exemplo, toMillis()que converte em milissegundos.
Emil Lunde
100

Reuniu todas as formas possíveis juntas em um só lugar.

Encontro

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 legível por 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;
}

Goiaba: Google Stopwatch JAR «Um objetivo do cronômetro é medir o tempo decorrido em nanossegundos.

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 «O StopWatch fornece uma API conveniente para horários.

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 -TIME

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 data e hora do Java do Java 8 «Um objeto Duration representa um período de tempo entre dois 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 

O Spring Framework fornece aclasse de utilitário StopWatch para medir o tempo decorrido em 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());
}

Resultado:

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
fonte
O cronômetro da Goiaba, Apache Commons e Spring Framework não são seguros para threads. Não é seguro para uso em produção.
Deepak Puthraya
@DeepakPuthraya, qual biblioteca usar e qual é segura para uso em produção?
gaurav
1
@DeepakPuthraya, você pode usar o Java 8, desde a API de data e hora do Java. O que é simples.
Yash
Na IMO, este post se beneficiaria se todas as soluções também mostrassem a saída das saídas do sistema.
BAERUS 28/04
87

Use um profiler (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler, etc). Você obterá os resultados mais precisos e é o menos invasivo. Eles usam o mecanismo interno da JVM para criação de perfil, que também pode fornecer informações extras, como rastreios de pilha, caminhos de execução e resultados mais abrangentes, se necessário.

Ao usar um criador de perfil totalmente integrado, é trivial criar um perfil de um método. Clique com o botão direito do mouse em Profiler -> Adicionar aos métodos raiz. Em seguida, execute o criador de perfil como se estivesse executando um teste ou depurador.

James Schek
fonte
Essa também foi uma ótima sugestão, e um daqueles momentos "duh" de lâmpada para mim quando li esta resposta. Nosso projeto usa o JDeveloper, mas eu verifiquei e, com certeza, ele possui um profiler embutido!
Ogre Psalm33
2
De java 7 build 40 (eu acho) que incluía os ex-JRockits gravador de vôo para java (procurar Java Mission Control)
Niels Bech Nielsen
Com certeza @NielsBechNielsen! oracle.com/technetwork/java/javaseproducts/mission-control/...
Ogre Psalm33
Como obter a execução do método em Java pelo Visual VM, por exemplo?
OKWAP
41

Provavelmente não é isso que você queria que eu dissesse, mas esse é um bom uso da AOP. Use um interceptador proxy no seu método e faça o tempo necessário.

Infelizmente, o que, por que e como da AOP está além do escopo desta resposta, mas é assim que eu provavelmente faria.

Edit: Aqui está um link para o Spring AOP para você começar, se você estiver interessado. Esta é a implementação mais acessível do AOP que eu encontrei para java.

Além disso, dadas as sugestões muito simples de todos os outros, devo acrescentar que o AOP é para quando você não quer coisas como o tempo para invadir seu código. Mas em muitos casos, esse tipo de abordagem simples e fácil é bom.

skaffman
fonte
3
Aqui está um tutorial sobre como fazer isso com o Spring: veerasundar.com/blog/2010/01/…
David Tinker
39

System.currentTimeMillis();NÃO é uma boa abordagem para medir o desempenho de seus algoritmos. Ele mede o tempo total que você experimenta como usuário assistindo à tela do computador. Ele também inclui o tempo consumido por todo o resto em execução no seu computador em segundo plano. Isso pode fazer uma enorme diferença caso você tenha muitos programas em execução na sua estação de trabalho.

A abordagem adequada é usar o java.lang.managementpacote.

No site http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking :

  • "Tempo do usuário" é o tempo gasto executando o código do seu aplicativo.
  • "Tempo do sistema" é o tempo gasto executando o código do SO em nome do seu aplicativo (como para E / S).

getCpuTime() O método fornece a soma desses:

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
fonte
4
Esse é definitivamente um bom ponto, pois o "tempo do usuário" (horário do relógio de parede) nem sempre é uma ótima medida de desempenho, especialmente em um programa multithread.
quer tocar
Esta é a resposta que estou procurando.
ZhaoGang 6/01
30

Com o Java 8, você também pode fazer algo assim com todos os métodos normais :

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

com TimeIt como:

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

Com esse método, você pode fazer uma medição fácil do tempo em qualquer lugar do seu código sem quebrá-lo. Neste exemplo simples, apenas imprimo a hora. Você pode adicionar um Switch for TimeIt, por exemplo, para imprimir apenas a hora no DebugMode ou algo assim.

Se você estiver trabalhando com o Function, poderá fazer algo assim:

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
fonte
Isso parece muito melhor do que outras soluções. É mais perto da Spring AOP, mas mais leve que isso. Verdadeiro java 8 way! +1 Obrigado!
Amit Kumar
Talvez isso pareça bom para você, porque Stefan está usando novas funções java sofisticadas. Mas acho que isso é extremamente difícil de ler e entender.
achou do
18

Também podemos usar a classe StopWatch dos bens comuns do Apache para medir o tempo.

Código de amostra

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
fonte
15

Apenas uma pequena reviravolta, se você não usar ferramentas e quiser cronometrar métodos com baixo tempo de execução: execute-o várias vezes, sempre que dobrar o número de vezes em que é executado até chegar a um segundo, aproximadamente. Portanto, a hora da chamada para System.nanoTime e assim por diante, nem a precisão de System.nanoTime afetam muito o 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");

Obviamente, as advertências sobre o uso do relógio de parede se aplicam: influências da compilação JIT, vários encadeamentos / processos etc. Portanto, é necessário primeiro executar o método várias vezes primeiro, para que o compilador JIT faça seu trabalho e depois repita esse teste várias vezes e tome o menor tempo de execução.

Hans-Peter Störr
fonte
13

Estamos usando anotações AspectJ e Java para esse fim. Se precisarmos saber o tempo de execução de um método, simplesmente o anotamos. Uma versão mais avançada pode usar um nível de log próprio que pode ser ativado e desativado no tempo de execução.

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;
  }
  [...]
}

fonte
13

JEP 230: Suíte Microbenchmark

FYI, JEP 230: Microbenchmark Suite é um projeto OpenJDK para:

Adicione um conjunto básico de marcas de microbench ao código-fonte do JDK e facilite aos desenvolvedores a execução de marcas de microbench existentes e crie novas.

Esse recurso chegou no Java 12 .

Arnês de Microbenchmark Java (JMH)

Para versões anteriores do Java, dê uma olhada no projeto Java Microbenchmark Harness (JMH) no qual o JEP 230 se baseia.

Basil Bourque
fonte
11

Código realmente bom.

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
fonte
3
Na verdade, a questão era como calcular a quantidade de tempo que um método leva, não como formatá-lo. No entanto, esta questão é bastante antiga (quase quatro anos!). Tente evitar ressuscitar threads antigos, a menos que a resposta adicione algo novo e significativo às respostas existentes.
Leigh
1
E para adicionar millis restantes até o fim, faça as seguintes alterações: 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
10

Você pode usar o Perf4j . Utilitário muito legal. O uso é simples

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

Mais informações podem ser encontradas no Guia do desenvolvedor

Edit: Projeto parece morto

mergenchik
fonte
1
O Perf4j também pode gerar boas estatí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
fonte
1
Rolar sua própria classe simples é uma boa opção quando você já possui o sistema de compilação e o OTS dependente configurado e não deseja se preocupar em extrair outro pacote OTS que inclua uma classe de timer de utilitário.
Ogre Psalm33
7

Basicamente, faço variações disso, mas, considerando o funcionamento da compilação do ponto de acesso, se você deseja obter resultados precisos, precisa realizar as primeiras medições e garantir que está usando o método em um aplicativo do mundo real (leia-se o aplicativo).

Se o JIT decidir compilá-lo, seus números variarão bastante. então fique atento

Lucas
fonte
7

Usando AOP / AspectJ e @Loggableanotação de jcabi-aspect, você pode fazer isso de maneira fácil e compacta:

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

Todas as chamadas para esse método serão enviadas para o recurso de log do SLF4J com DEBUGnível de log. E toda mensagem de log incluirá tempo de execução.

yegor256
fonte
7

O Spring fornece uma classe de utilitário org.springframework.util.StopWatch , conforme JavaDoc:

Cronômetro simples, permitindo o tempo de várias tarefas, expondo o tempo total e o tempo de execução para cada tarefa nomeada.

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

Resultado:

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

Com 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
fonte
É possível usar isso com o AspectJ?
Zygimantus 20/10/2015
7

Eu escrevi um método para imprimir o tempo de execução do método de uma forma muito legível. Por exemplo, para calcular o fatorial de 1 milhão, leva aproximadamente 9 minutos. Portanto, o tempo de execução é impresso como:

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

O código está aqui:

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
fonte
6

Existem algumas maneiras de fazer isso. Normalmente, volto a usar algo assim:

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

ou a mesma coisa com System.nanoTime ();

Para algo mais sobre o lado do benchmarking, parece haver também este: http://jetm.void.fm/ Mas nunca tentei.

Horst Gutmann
fonte
6

Você pode usar a biblioteca Metrics , que fornece vários instrumentos de medição. Adicionar dependência:

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

E configure-o para o seu ambiente.

Os métodos podem ser anotados com @Timed :

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

ou parte do código envolvido com Timer :

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

Métricas agregadas podem ser exportadas para console, JMX, CSV ou outro.

@Timed exemplo de saída 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
Assim como
fonte
5

Se você quiser o relógio de parede

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

Como "skaffman" disse, use AOP OU você pode usar a tecelagem por código de tempo de execução, assim como as ferramentas de cobertura do método de teste de unidade usam para adicionar de forma transparente informações de tempo aos métodos invocados.

Você pode ver o código usado por ferramentas de ferramentas de código aberto, como Emma ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ). A outra ferramenta de cobertura de código aberto é http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download .

Se você finalmente conseguir fazer o que deseja, pls. compartilhe-o de volta com a comunidade aqui com suas tarefas / frascos de formigas.

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

Modifiquei o código da resposta correta para obter o resultado em 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
fonte
4

Você pode usar a classe cronômetro do projeto principal da 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

Documentação para cronômetro: cronômetro simples, permitindo o tempo de várias tarefas, expondo o tempo total e o tempo de execução de cada tarefa nomeada. Esconde o uso de System.currentTimeMillis (), melhorando a legibilidade do código do aplicativo e reduzindo a probabilidade de erros de cálculo. Observe que este objeto não foi projetado para ser seguro para threads e não usa sincronização. Essa classe é normalmente usada para verificar o desempenho durante a prova de conceitos e no desenvolvimento, e não como parte dos aplicativos de produção.

praveen jain
fonte
3

Você pode tentar dessa maneira se quiser saber a hora.

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

Ok, esta é uma classe simples a ser usada para o tempo simples e simples de suas funções. Há um exemplo abaixo.

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

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

Amostra de saída do console:

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

No Java 8, uma nova classe denominada Instanté introduzida. Conforme o documento:

Instantâneo representa o início de um nanossegundo na linha do tempo. Essa classe é útil para gerar um registro de data e hora para representar o horário da máquina. O intervalo de um instante requer o armazenamento de um número maior que um longo. Para conseguir isso, a classe armazena um longo representando a época-segundo e um int representando o nanossegundo de segundo, que sempre estará entre 0 e 999.999.999. A época-segundo é medida a partir da época Java padrão de 01-01-2009: 00: 00Z, em que os instantes após a época têm valores positivos e os instantes anteriores têm valores negativos. Para as partes da época do segundo e nanossegundos, um valor maior é sempre mais tarde na linha do tempo do que um valor menor.

Isso pode ser usado 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));

Imprime PT7.001S.

akhil_mittal
fonte