Come faccio a programmare l'esecuzione di un metodo in Java?


834
  1. Come posso ottenere i tempi di esecuzione di un metodo?
  2. Esiste una Timerclasse di utilità per cose come il tempo che richiede un'attività, ecc.?

La maggior parte delle ricerche su Google restituisce risultati per timer che programmano discussioni e attività, che non è quello che voglio.


L'API JAMon è un'API Java gratuita, semplice, ad alte prestazioni, thread-safe, che consente agli sviluppatori di monitorare facilmente le prestazioni e la scalabilità delle applicazioni di produzione. JAMon tiene traccia di hit, tempi di esecuzione (totale, media, minima, massima, deviazione standard) e altro. http://jamonapi.sourceforge.net/ download: http://sourceforge.net/project/showfiles.php?group_id=96550
Mike Pone

1
Potresti anche dare un'occhiata alla classe Lang StopWatch di Apache Commons . Una classe di utilità semplice ma utile.


Sì, StopWatch è ottimo per questo.
Shubham Pandey,

Risposte:


1208

C'è sempre il vecchio stile:

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

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

234
in realtà, è "nuovo stile" perché hai usato nanoTime, che non è stato aggiunto fino a java5
John Gardner,

11
Questo (o usando System.currentTimeMillis ()) sembra essere il modo in cui viene fatto di solito in Java ... che ho visto comunque. Mi sorprende ancora leggermente che non ci sia una classe incorporata spiffy, come Timer t = new Timer (); String s = t.getElapsed (formato); ecc ...
Ogre Salmo33

18
nanoTime non garantisce una precisione migliore di currentTimeMillis (), sebbene di solito lo faccia. forums.sun.com/thread.jspa?messageID=9460663 e simongbrown.com/blog/2007/08/20/…
James Schek

10
Ovviamente, è sempre importante ricordare le insidie ​​del micro-benchmarking, come le ottimizzazioni del compilatore / JVM che possono distorcere il risultato = Cool)
Yuval

18
Non è necessario un blocco finally poiché endTime non verrà utilizzato se viene generata un'eccezione.
Peter Lawrey,

197

Vado con la semplice risposta. Per me va bene.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

Funziona abbastanza bene. La risoluzione è ovviamente solo al millisecondo, puoi fare di meglio con System.nanoTime (). Esistono alcuni limiti per entrambi (sezioni di pianificazione del sistema operativo, ecc.), Ma funziona abbastanza bene.

Media in un paio di corse (più meglio è) e avrai un'idea decente.


51
In realtà, System.currentTimeMillis () ha una precisione superiore a 15ms. Per valori davvero bassi non ci si può fidare. La soluzione per questo (come detto) è System.nanoTime ();
Steve g

Ok, stavo per accettarlo come risposta ufficiale fino a quando non ho letto il commento di Steve G. Ottima notizia, Steve!
Ogre Salmo33

4
nanoTime () non garantisce una precisione migliore di currentTimeMillis, ma molte implementazioni JVM hanno una migliore precisione con nanoTime.
James Schek,

5
@JamesSchek Hai davvero bisogno di guardare il tuo testo, come ho già detto in questo identico commento altrove; nanoTimeè garantito per essere risoluto almeno quanto currentTimeMillis. docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy

L'unico piccolo vantaggio currentTimeMillisè che si tratta di un timestamp effettivo e potrebbe essere utilizzato anche per registrare i tempi di inizio / fine, mentre nanoTime"può essere utilizzato solo per misurare il tempo trascorso e non è correlato a nessun'altra nozione di tempo di sistema o di orologio da parete ".
Brad Parks,

177

Forza ragazzi! Nessuno ha menzionato il modo Guava di farlo (che è probabilmente fantastico):

import com.google.common.base.Stopwatch;

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

La cosa bella è che Stopwatch.toString () fa un buon lavoro nella selezione delle unità di tempo per la misurazione. Cioè se il valore è piccolo, produrrà 38 ns, se è lungo, mostrerà 5m 3s

Ancora più bello:

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

Nota: Google Guava richiede Java 1.6+


21
Sfortunatamente, il cronometro di Guava non è thread-safe. l'ho imparato a mie spese.
Dexter Legaspi,

6
@DexterLegaspi Sarebbe molto interessato alla tua esperienza! Vuoi condividere?
Siddhartha,

1
L'uso del cronometro in parallelo porterebbe a chiamare start()più volte di seguito (lo stesso per stop()).
Mingwei Samuel,

141

Utilizzando Instant e Duration dalla nuova API di Java 8,

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

uscite,

PT5S

2
Grazie, come posso ottenere il risultato senza avere il PT davanti?
java123999,

1
Il problema con il metodo è che Instant non presenta problemi di precisione millimetrica e nano di seconda. Rif: stackoverflow.com/questions/20689055/…
prashantsunkari

8
@ java123999: puoi chiamare Duration.between(start, end).getSeconds(). Durationha anche metodi per convertire in altre unità di tempo, ad es. toMillis()che converte in millisecondi.
Emil Lunde,

100

Riuniti tutti i modi possibili insieme in un unico posto.

Data

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 leggibile dall'uomo

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 Stopwatch JAR «Un oggetto di Stopwatch è misurare il tempo trascorso in nanosecondi.

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 fornisce un'API conveniente per gli orari.

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 data e ora Java da Java 8 «Un oggetto Duration rappresenta un periodo di tempo tra due oggetti Instant .

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 fornisce laclasse di utilità StopWatch per misurare il tempo trascorso in 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());
}

Produzione:

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]

Cronometro di Guava, Apache Commons e Spring Framework non sono thread-safe. Non sicuro per l'utilizzo in produzione.
Deepak Puthraya,

@DeepakPuthraya quindi quale libreria utilizzare quale è sicura per l'utilizzo in produzione?
gaurav

1
@DeepakPuthraya puoi usare l'API Java data / ora fornita da Java 8. Che è semplice.
Yash

IMO questo post trarrebbe beneficio se ogni soluzione mostrasse anche l'output degli out di sistema.
BAERUS

87

Utilizzare un profiler (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler, ecc.). Otterrai i risultati più accurati ed è il meno invadente. Usano il meccanismo JVM integrato per la creazione di profili che può anche fornire informazioni extra come tracce di stack, percorsi di esecuzione e risultati più completi, se necessario.

Quando si utilizza un profiler completamente integrato, è banale eseguire il profiling di un metodo. Tasto destro del mouse, Profiler -> Aggiungi ai metodi di root. Quindi esegui il profiler proprio come se stessi eseguendo un test o un debugger.


Anche questo è stato un grande suggerimento, e uno di quei "duh" momenti di lampadina per me quando ho letto questa risposta. Il nostro progetto utilizza JDeveloper, ma ho controllato e, di sicuro, ha un profiler integrato!
Ogre Salmo33

2
Dalla java 7 build 40 (credo) includevano l'ex JRockits Flight Recorder a java (ricerca di Java Mission Control)
Niels Bech Nielsen


Come ottenere l'esecuzione del metodo in Java da Visual VM, ad esempio?
Okwap

41

Questo probabilmente non è quello che volevi che dicessi, ma questo è un buon uso di AOP. Montare un intercettore proxy attorno al metodo e fare il tempismo lì dentro.

Il cosa, perché e come di AOP è al di là dell'ambito di questa risposta, purtroppo, ma è così che probabilmente lo farei.

Modifica: ecco un link a Spring AOP per iniziare, se sei appassionato. Questa è l'implementazione più accessibile di AOP che Iive incontra per Java.

Inoltre, dati i suggerimenti molto semplici di tutti gli altri, dovrei aggiungere che AOP è per quando non vuoi che cose come il tempismo invadano il tuo codice. Ma in molti casi, questo tipo di approccio semplice e facile va bene.


3
Ecco un tutorial su come farlo con Spring: veerasundar.com/blog/2010/01/…
David Tinker,

39

System.currentTimeMillis();NON è un buon approccio per misurare le prestazioni dei tuoi algoritmi. Misura il tempo totale che hai trascorso come utente guardando lo schermo del computer. Include anche il tempo impiegato da tutto il resto in esecuzione sul computer in background. Ciò potrebbe fare un'enorme differenza nel caso in cui ci siano molti programmi in esecuzione sulla workstation.

L'approccio corretto sta usando il java.lang.managementpacchetto.

Dal sito Web http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking :

  • "Tempo utente" è il tempo impiegato per eseguire il codice dell'applicazione.
  • "Ora di sistema" è il tempo impiegato per eseguire il codice OS per conto dell'applicazione (ad esempio per l'I / O).

getCpuTime() il metodo ti dà la somma di quelli:

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

}

4
Questo è sicuramente un buon punto, che il "tempo dell'utente" (tempo dell'orologio da parete) non è sempre una grande misura delle prestazioni, specialmente in un programma multi-thread.
Ogre Salmo33

Questa è la risposta che sto cercando.
ZhaoGang

30

Con Java 8 puoi fare anche qualcosa del genere con tutti i metodi normali :

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

con TimeIt come:

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 questo metodo puoi eseguire facilmente la misurazione del tempo in qualsiasi punto del codice senza romperlo. In questo semplice esempio stampo l'ora. Puoi aggiungere un interruttore per TimeIt, ad esempio per stampare solo l'ora in modalità Debug o qualcosa del genere.

Se stai lavorando con Function puoi fare qualcosa del genere:

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

Sembra molto meglio di altre soluzioni. È più vicino a Spring AOP ma più leggero di così. Vero java 8 vie! +1 Grazie!
Amit Kumar,

Forse questo ti sta bene, perché Stefan sta usando nuove fantastiche funzioni Java. Ma penso che sia agevolmente difficile da leggere e capire.
Stimpson Cat,

18

Inoltre possiamo usare la classe StopWatch di comuni Apache per misurare il tempo.

Codice di esempio

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

15

Solo una piccola svolta, se non usi gli strumenti e vuoi cronometrare metodi con tempi di esecuzione bassi: esegui molte volte, ogni volta raddoppiando il numero di volte che viene eseguito fino a raggiungere un secondo, o giù di lì. Pertanto, il tempo della chiamata a System.nanoTime e così via, né l'accuratezza di System.nanoTime influiscono molto sul risultato.

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

Naturalmente, si applicano le avvertenze sull'uso dell'orologio da parete: influenze della compilazione JIT, più thread / processi ecc. Pertanto, è necessario prima eseguire il metodo molte volte prima, in modo tale che il compilatore JIT faccia il suo lavoro, quindi ripetere questo test più volte e impiegare il tempo di esecuzione più basso.


13

Per questo scopo stiamo usando le annotazioni AspectJ e Java. Se dobbiamo sapere i tempi di esecuzione di un metodo, lo annotiamo semplicemente. Una versione più avanzata potrebbe utilizzare un proprio livello di registro che può essere abilitato e disabilitato in fase di esecuzione.

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

13

JEP 230: Suite Microbenchmark

Cordiali saluti, JEP 230: Microbenchmark Suite è un progetto OpenJDK per:

Aggiungi una suite base di microbenchmark al codice sorgente JDK e semplifica gli sviluppatori per eseguire microbenchmark esistenti e crearne di nuovi.

Questa funzione è arrivata in Java 12 .

Cablaggio Microbenchmark Java (JMH)

Per le versioni precedenti di Java, dai un'occhiata al progetto Java Microbenchmark Harness (JMH) su cui si basa JEP 230.


11

Davvero un buon codice.

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

3
In realtà la domanda era come calcolare il tempo impiegato da un metodo, non come formattarlo. Tuttavia questa domanda è piuttosto vecchia (quasi quattro anni!). Cerca di evitare di resuscitare vecchi thread a meno che la risposta non aggiunga qualcosa di nuovo e significativo rispetto alle risposte esistenti.
Leigh,

1
E per aggiungere i millis rimanenti alla fine, apporta le seguenti modifiche: 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

Puoi usare Perf4j . Utilità molto interessante. L'utilizzo è semplice

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

Ulteriori informazioni sono disponibili in Guida per gli sviluppatori

Modifica: il progetto sembra morto


1
Perf4j può anche generare statistiche interessanti .
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()));
    }

}

1
Roll la tua classe semplice è una buona scelta quando hai già configurato il sistema di compilazione e OTS dipendente e non vuoi preoccuparti di inserire un altro pacchetto OTS che include una classe timer di utilità.
Ogre Salmo33

7

Fondamentalmente faccio variazioni di questo, ma considerando come funziona la compilazione di hotspot, se vuoi ottenere risultati accurati devi buttare via le prime misurazioni e assicurarti di utilizzare il metodo in un'applicazione reale (leggi specifica dell'applicazione).

Se la JIT decide di compilarla, i tuoi numeri varieranno notevolmente. quindi basta essere consapevoli


7

Usando AOP / AspectJ e @Loggableannotazioni da aspetti jcabi puoi farlo in modo facile e compatto:

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

Ogni chiamata a questo metodo verrà inviata alla funzione di registrazione SLF4J con DEBUGlivello di registrazione. E ogni messaggio di registro includerà i tempi di esecuzione.


7

Spring fornisce una classe di utilità org.springframework.util.StopWatch , secondo JavaDoc:

Cronometro semplice, che consente la temporizzazione di una serie di attività, esponendo il tempo di esecuzione totale e il tempo di esecuzione per ciascuna attività denominata.

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

Produzione:

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

Con aspetti:

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

È possibile usarlo con AspectJ?
zygimantus,

7

Ho scritto un metodo per stampare il tempo di esecuzione del metodo in una forma molto leggibile. Ad esempio, per calcolare il fattoriale di 1 milione, sono necessari circa 9 minuti. Quindi i tempi di esecuzione vengono stampati come:

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

Il codice è qui:

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

6

Ci sono un paio di modi per farlo. Di solito torno a usare qualcosa del genere:

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

o la stessa cosa con System.nanoTime ();

Per qualcosa di più sul lato benchmarking delle cose sembra esserci anche questo: http://jetm.void.fm/ Non l'ho mai provato.


6

È possibile utilizzare la libreria Metrics che fornisce vari strumenti di misurazione. Aggiungi dipendenza:

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

E configuralo per il tuo ambiente.

I metodi possono essere annotati con @Timed :

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

o pezzo di codice avvolto con Timer :

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

Le metriche aggregate possono essere esportate su console, JMX, CSV o altro.

@Timed esempio di output delle metriche:

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

5

Se vuoi l'ora dell'orologio da parete

long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;

5

Come ha detto "skaffman", utilizzare AOP OPPURE è possibile utilizzare la tessitura bytecode del tempo di esecuzione, proprio come gli strumenti di copertura dei metodi di test unitari utilizzano per aggiungere in modo trasparente informazioni sui tempi ai metodi richiamati.

Puoi guardare il codice utilizzato dagli strumenti di strumenti open source come Emma ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ). L'altro strumento di copertura opensource è http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download .

Se alla fine riesci a fare ciò per cui ti impegni, pls. condividilo di nuovo con la community qui con i tuoi compiti / vasetti di formiche.


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

4

Ho modificato il codice dalla risposta corretta per ottenere il risultato in pochi secondi:

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

4

È possibile utilizzare la classe cronometro dal progetto core di primavera:

Codice:

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

Documentazione per cronometro: cronometro semplice, che consente la temporizzazione di una serie di attività, esponendo il tempo di esecuzione totale e il tempo di esecuzione per ciascuna attività denominata. Nasconde l'uso di System.currentTimeMillis (), migliorando la leggibilità del codice dell'applicazione e riducendo la probabilità di errori di calcolo. Si noti che questo oggetto non è progettato per essere thread-safe e non utilizza la sincronizzazione. Questa classe viene normalmente utilizzata per verificare le prestazioni durante la prova dei concetti e nello sviluppo, piuttosto che come parte delle applicazioni di produzione.


3

Puoi provare in questo modo se vuoi solo sapere l'ora.

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

3

Ok, questa è una classe semplice da usare per un semplice cronometraggio delle tue funzioni. C'è un esempio sotto di esso.

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

Esempio di utilizzo:

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

Esempio di output della console:

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

3

In Java 8 Instantviene introdotta una nuova classe denominata . Come da documento:

Instant rappresenta l'inizio di un nanosecondo sulla linea del tempo. Questa classe è utile per generare un timestamp per rappresentare il tempo della macchina. L'intervallo di un istante richiede la memorizzazione di un numero maggiore di un lungo. Per raggiungere questo obiettivo, la classe memorizza un lungo che rappresenta epoche-secondi e un int che rappresenta nanosecondi di secondo, che sarà sempre compreso tra 0 e 999.999.999. I secondi dell'epoca sono misurati dall'epoca Java standard del 1970-01-01T00: 00: 00Z in cui gli istanti dopo l'epoca hanno valori positivi e gli istanti precedenti hanno valori negativi. Sia per le parti in epoche di secondo che per i nanosecondi, un valore più grande è sempre più tardi sulla linea temporale di un valore più piccolo.

Questo può essere usato come:

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

Stampa PT7.001S .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.