2010-04-03 5 views
64

Désolé, cela peut vous sembler une question stupide, mais comment chronométrer l'exécution d'un programme java? Je ne suis pas sûr de quelle classe je devrais utiliser pour faire ceci.Comment chronométrer la vitesse d'exécution du programme Java

Je cherche un peu pour quelque chose comme:

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

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

Merci

Répondre

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

Espérons que cela a aidé.

+1

il devrait vraiment être nanoTime réellement – Eugene

+4

Ne devrait pas être nanoTime. Voir la réponse de rhu. – fabspro

+3

Y at-il une raison particulière pour laquelle vous avez utilisé "final" ici? Qu'est-ce qui serait différent si vous perdiez ce mot-clé? – dijxtra

7

Vous pouvez utiliser des System#nanoTime(). Obtenez-le avant et après l'exécution et faites le calcul. Il est préféré au dessus de System#currentTimeMillis() car il a une meilleure précision. En fonction du matériel et de la plate-forme utilisés, vous risquez d'obtenir un écart incorrect en termes de temps écoulé. Ici, avec Core2Duo sous Windows, entre 0 et ~ 15ms, rien ne peut être calculé.

Un outil plus avancé est un profiler.

+0

Le temporisateur sous Windows n'a pas une résolution particulièrement bonne par défaut. Il ya * un * minuteur de haute performance aussi, mais il est beaucoup plus difficile à utiliser même à partir de C et Java n'a pas (AFAIK) fournir un accès à ce bas niveau de hackery sans un junk JNI. –

+0

+1 pour le lien du profileur. –

+1

'nanoTime()' a un problème (au moins sous Windows); l'horodatage est spécifique au cœur du processeur. J'ai eu un programme qui a eu un temps d'exécution négatif car il a reçu l'horodatage "start" sur un core, et l'horodateur "stop" sur un autre core. – gustafc

6

Vous obtenez le temps de système actuel, en millisecondes:

final long startTime = System.currentTimeMillis(); 

Ensuite, vous faites ce que vous allez faire:

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

Ensuite, vous voyez combien de temps il a fallu:

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

La réponse de BalusC est également correcte; cela dépend de la résolution de minuterie nécessaire, et pourquoi vous avez besoin de la synchronisation. –

1

utilisation à long startTime=System.currentTimeMillis() pour le temps de démarrage, au sommet de la boucle

mis long endTime= System.currentTimeMillis(); en dehors de la fin de la boucle. Vous devrez soustraire les valeurs pour obtenir l'exécution en millisecondes.

Si vous voulez temps en nanosecondes, consultez System.nanoTime()

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

Soyez conscient qu'il ya des questions sur lesquelles System#nanoTime() ne peut pas être utilisé de manière fiable à enregistrer le temps écoulé CPU multi-core ... chaque noyau a maintient son propre TSC (Time Stamp Counter): ce compteur est utilisé pour obtenir le nano time (en réalité c'est le nombre de ticks depuis le démarrage du CPU). Par conséquent, à moins que le système d'exploitation ne déforme le temps TSC pour maintenir la synchronisation des coeurs, si un thread est programmé sur un cœur lors de la lecture de l'heure initiale, puis sur un autre noyau, le temps relatif peut sporadiquement semblent sauter en arrière et en avant. Je l'ai observé il y a quelque temps sur AMD/Solaris où les temps écoulés entre deux points de temporisation revenaient parfois sous la forme de valeurs négatives ou de nombres positifs inattendus. Il y avait un patch de noyau Solaris et un paramètre BIOS requis pour forcer le AMD PowerNow! off, qui semblait l'avoir résolu.

En outre, il y a (AFAIK) un bogue non-fixé jusqu'à présent lors de l'utilisation de Java System#nanoTime() dans un environnement VirtualBox; causant toutes sortes de problèmes de threading intermittents bizarres pour nous autant du paquet java.util.concurrency repose sur nano time.

Voir aussi:

Is System.nanoTime() completely useless? http://vbox.innotek.de/pipermail/vbox-trac/2010-January/135631.html

+3

+1 pour une explication claire des lacunes de nanoTime. – Jason

3

Pour des choses simples, System.currentTimeMillis() peut fonctionner.

Il est en fait si commun que mon IDE est configuré de telle sorte que lors de l'entrée « t0 » il me génère la ligne suivante:

final long t0 = System.currentTimeMillis() 

Mais pour les choses plus compliquées, vous aurez probablement envie d'utiliser des mesures de temps statistiques , comme ici (faire défiler vers le bas un peu et regarder les mesures de temps exprimé, y compris les écarts-types, etc.):

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

+0

+1 pour indiquer le code du générateur automatique. J'utilise une instruction similaire tout le temps et je ne savais pas comment insérer des templates de code. Juste découvert comment faire cela avec éclipse, et il va certainement aider! – Jason

+0

Tous les services Codehaus ont été arrêtés. Votre lien est maintenant cassé. – naXa

0

Vous pouvez également essayer Perf4J. C'est une façon élégante de faire ce que vous recherchez, et aide dans les statistiques agrégées de performance comme la moyenne, le minimum, le maximum, l'écart-type et les transactions par seconde sur une période donnée. Un extrait de 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); 
} 

Sortie:

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

En utilisant System.currentTimeMillis() est la bonne façon de le faire. Mais, si vous utilisez la ligne de commande, et que vous voulez en temps l'ensemble du programme environ et rapidement, pensez à:

time java App 

qui vous permet de ne pas modifier le code et l'heure de votre application.

+0

Cela dépend de la façon dont vous exécutez le code. Si c'est un morceau de code exécutant un serveur, alors vous allez inclure l'heure de démarrage qui est incorrecte. –

2

utilisant AOP/AspectJ et @Loggable annotation de jcabi-aspects vous pouvez le faire facilement et compact:

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

Chaque appel à cette méthode sera envoyée à l'installation d'enregistrement SLF4J avec DEBUG niveau de journalisation. Et chaque message de journal inclura le temps d'exécution.

Questions connexes