Come calcolare la velocità di esecuzione del programma Java


85

Come cronometri l'esecuzione di un programma Java? Non sono sicuro di quale classe dovrei usare per farlo.

Sto cercando qualcosa come:

// Some timer starts here
for (int i = 0; i < length; i++) {
  // Do something
}
// End timer here

System.out.println("Total execution time: " + totalExecutionTime);

Risposte:


139
final long startTime = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
  // Do something
}
final long endTime = System.currentTimeMillis();

System.out.println("Total execution time: " + (endTime - startTime));

2
dovrebbe essere davvero nanoTime in realtà
Eugene

6
Non dovrebbe essere nanoTime. Vedi la risposta di rhu.
fabspro

4
C'è qualche motivo particolare per cui hai usato "finale" qui? Cosa sarebbe diverso se abbandonassi quella parola chiave?
dijxtra

9
L'utilizzo di @dijxtra finalha il vantaggio che non puoi assegnargli accidentalmente (così come altri vantaggi, come l'accesso anonimo alla classe, ecc.). In questo codice non farebbe differenza. È una pratica abbastanza comune fare tutto finale finaldisabilitarlo solo se necessario.
wchargin

1
Il codice da testare, insieme alle misurazioni del tempo, dovrebbe essere eseguito più volte e il primo risultato dovrebbe essere scartato. Il primo probabilmente includerà i tempi di caricamento della classe, ecc. Eseguendolo anche più volte, ovviamente, si ottiene una media più utile e affidabile.
Arun Ramakrishnan

34

Tieni presente che ci sono alcuni problemi in cui System#nanoTime()non può essere utilizzato in modo affidabile su CPU multi-core per registrare il tempo trascorso ... ogni core ha il proprio TSC ( Time Stamp Counter ): questo contatore viene utilizzato per ottenere il nano tempo (in realtà lo è il numero di tick dall'avvio della CPU).

Quindi, a meno che il sistema operativo non esegua un time warping TSC per mantenere i core sincronizzati, se un thread viene programmato su un core quando viene eseguita la lettura dell'ora iniziale, quindi passa a un core diverso, il tempo relativo può sporadicamente sembrare che salti all'indietro e in avanti.

L'ho osservato qualche tempo fa su AMD / Solaris dove i tempi trascorsi tra due punti di temporizzazione a volte tornavano come valori negativi o numeri positivi inaspettatamente grandi. C'era una patch del kernel Solaris e un'impostazione del BIOS necessaria per forzare AMD PowerNow! off, che sembrava risolverlo.

Inoltre, c'è (AFAIK) un bug fino ad ora non risolto quando si utilizza java System#nanoTime()in un ambiente VirtualBox; causando tutti i tipi di bizzarri problemi di threading intermittenti per noi poiché gran parte del java.util.concurrencypacchetto si basa sul tempo nano.

Guarda anche:

System.nanoTime () è completamente inutile? http://vbox.innotek.de/pipermail/vbox-trac/2010-January/135631.html


9

Ottieni l'ora di sistema corrente, in millisecondi:

final long startTime = System.currentTimeMillis();

Quindi fai quello che stai per fare:

for (int i = 0; i < length; i++) {
  // Do something
}

Quindi vedi quanto tempo ci è voluto:

final long elapsedTimeMillis = System.currentTimeMillis() - startTime;

Anche la risposta di BalusC è corretta; dipende dalla risoluzione del timer necessaria e dal motivo per cui è necessario il tempismo.
Jonathan Feinberg

9

Puoi usare System#nanoTime(). Scaricalo prima e dopo l'esecuzione e fai i conti. È preferibile sopra System#currentTimeMillis()perché ha una precisione migliore. A seconda dell'hardware e della piattaforma utilizzata, potresti altrimenti ottenere un intervallo errato nel tempo trascorso. Qui con Core2Duo su Windows, tra circa 0 e ~ 15 ms in realtà non è possibile calcolare nulla.

Uno strumento più avanzato è un profiler .


Il timer su Windows non ha una risoluzione particolarmente buona per impostazione predefinita. V'è un timer ad alte prestazioni troppo, ma è molto più difficile da usare anche da C e Java non (per quanto ne so) che forniscono l'accesso a basso livello di aggiustamenti senza un JNI thunk.
Donal Fellows

1
nanoTime()ha un problema (almeno su Windows); il timestamp è specifico per il core del processore. Avevo un programma che ha un tempo di esecuzione negativo perché ha il timestamp "start" su un core e il timestamp "stop" su un altro core.
gustafc

3

Per cose semplici, System.currentTimeMillis () può funzionare.

In realtà è così comune che il mio IDE sia configurato in modo tale che inserendo "t0" mi generi la seguente riga:

final long t0 = System.currentTimeMillis()

Ma per cose più complicate, probabilmente vorrai usare misurazioni statistiche del tempo, come qui (scorri un po 'verso il basso e guarda le misurazioni del tempo espresse comprese le deviazioni standard ecc.):

http://perf4j.codehaus.org/devguide.html


+1 per indicare il codice del generatore automatico. Uso sempre un'affermazione simile e non sapevo come inserire modelli di codice. Ho appena scoperto come farlo con eclipse e sarà sicuramente d'aiuto!
Jason

Tutti i servizi Codehaus sono stati terminati. Il tuo collegamento è ora interrotto.
naXa

2

Usando AOP / AspectJ e l' @Loggableannotazione da jcabi -aspects puoi farlo in modo semplice e compatto:

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

Ogni chiamata a questo metodo verrà inviata alla struttura di registrazione SLF4J con DEBUGlivello di registrazione. E ogni messaggio di registro includerà il tempo di esecuzione.


2

Ecco alcuni modi per trovare il tempo di esecuzione in Java:

1) System.nanoTime ()

long startTime = System.nanoTime();
.....your code....
long endTime   = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in nanoseconds  : " + totalTime);
System.out.println("Execution time in milliseconds : " + totalTime / 1000000);

2) System.currentTimeMillis ()

long startTime = System.currentTimeMillis();
.....your code....
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds  : " + totalTime);

3) Instant.now ()

long startTime = Instant.now().toEpochMilli();
.....your code....
long endTime = Instant.now().toEpochMilli();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

o

Instant start = Instant.now();
.....your code....
Instant end = Instant.now();
Duration interval = Duration.between(start, end);
System.out.println("Execution time in seconds: " +interval.getSeconds());

4) Date.getTime ()

long startTime = new Date().getTime();
.....your code....
long endTime = new Date().getTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

1

utilizzare long startTime=System.currentTimeMillis()per l'ora di inizio, all'inizio del ciclo

mettere long endTime= System.currentTimeMillis();fuori dalla fine del ciclo. Dovrai sottrarre i valori per ottenere il runtime in millisecondi.

Se vuoi il tempo in nanosecondi, controlla System.nanoTime()


1

Ho creato una funzione di ordine superiore che prende il codice che vuoi misurare in / come lambda:

class Utils {

    public static <T> T timeIt(String msg, Supplier<T> s) {
        long startTime = System.nanoTime();
        T t = s.get();
        long endTime = System.nanoTime();
        System.out.println(msg + ": " + (endTime - startTime) + " ns");
        return t;
    }

    public static void timeIt(String msg, Runnable r) {
       timeIt(msg, () -> {r.run(); return null; });
    }
}

Chiamalo così:

Utils.timeIt("code 0", () ->
        System.out.println("Hallo")
);

// in case you need the result of the lambda
int i = Utils.timeIt("code 1", () ->
        5 * 5
);

Produzione:

codice 0: 180528 ns
codice 1: 12003 ns

Un ringraziamento speciale ad Andy Turner che mi ha aiutato a ridurre il licenziamento. Vedi qui .



0

Puoi anche provare Perf4J. È un modo accurato per fare ciò che stai cercando e aiuta nelle statistiche aggregate sulle prestazioni come media, minima, massima, deviazione standard e transazioni al secondo in un intervallo di tempo impostato. Un estratto da http://perf4j.codehaus.org/devguide.html :

StopWatch stopWatch = new LoggingStopWatch();

try {
    // the code block being timed - this is just a dummy example
    long sleepTime = (long)(Math.random() * 1000L);
    Thread.sleep(sleepTime);
    if (sleepTime > 500L) {
        throw new Exception("Throwing exception");
    }

    stopWatch.stop("codeBlock2.success", "Sleep time was < 500 ms");
} catch (Exception e) {
    stopWatch.stop("codeBlock2.failure", "Exception was: " + e);
}

Produzione:

INFO: start[1230493236109] time[447] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493236719] time[567] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493237286] time[986] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493238273] time[194] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238467] time[463] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238930] time[310] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239241] time[610] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493239852] time[84] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239937] time[30] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239968] time[852] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]

0
public class someClass
{
   public static void main(String[] args) // your app start point
   {
       long start = java.util.Calendar.getInstance().getTimeInMillis();

       ... your stuff ...

       long end = java.util.Calendar.getInstance().getTimeInMillis();
       System.out.println("it took this long to complete this stuff: " + (end - start) + "ms");
   }
}

0

L'uso di System.currentTimeMillis () è il modo corretto per farlo. Tuttavia, se utilizzi la riga di comando e desideri temporizzare l'intero programma in modo approssimativo e rapido, pensa a:

time java App

che ti permette di non modificare il codice e l'ora della tua App.


Dipende da come esegui il codice. Se si tratta di un pezzo di codice che esegue un server, includerai l'ora di avvio che non è corretta.
Arun Ramakrishnan
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.