Comment chronométrer l'exécution d'une méthode en Java?

834
  1. Comment obtenir le temps d'exécution d'une méthode?
  2. Existe-t-il une Timerclasse d'utilité pour des choses comme le chronométrage de la durée d'une tâche, etc.?

La plupart des recherches sur Google renvoient des résultats pour les minuteries qui planifient les threads et les tâches, ce qui n'est pas ce que je veux.

Psaume Ogre33
la source
L'API JAMon est une API Java gratuite, simple, hautes performances et sécurisée qui permet aux développeurs de surveiller facilement les performances et l'évolutivité des applications de production. JAMon suit les hits, les temps d'exécution (total, moy, min, max, dev std), et plus encore. http://jamonapi.sourceforge.net/ téléchargement: http://sourceforge.net/project/showfiles.php?group_id=96550
Mike Pone
1
Vous pouvez également consulter la classe Apache Commons Lang StopWatch . Une classe utilitaire simple mais utile.
Question similaire ultérieure: comment puis-je écrire un micro-benchmark correct en Java?
Basil Bourque
Oui, StopWatch est idéal pour cela.
Shubham Pandey
Java 8 utilisant la Instantclasse: stackoverflow.com/a/30975902/1216775
akhil_mittal

Réponses:

1208

Il y a toujours la méthode à l'ancienne:

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

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
Diastrophisme
la source
234
en fait, c'est "à la mode" parce que vous avez utilisé nanoTime, qui n'a pas été ajouté avant java5
John Gardner
11
Cela (ou l'utilisation de System.currentTimeMillis ()) semble être la façon dont cela se fait habituellement en Java ... que j'ai vu de toute façon. Il me surprend encore légèrement qu'il n'y a pas de classe intégrée, comme Timer t = new Timer (); Chaîne s = t.getElapsed (format); etc ...
Ogre Psalm33
18
nanoTime ne garantit pas une précision meilleure que currentTimeMillis (), bien qu'il le fasse généralement. forums.sun.com/thread.jspa?messageID=9460663 et simongbrown.com/blog/2007/08/20/…
James Schek
10
Bien sûr, il est toujours important de se rappeler les pièges du micro-benchmarking, tels que les optimisations de compilateur / JVM qui peuvent fausser le résultat = 8-)
Yuval
18
Il n'y a pas besoin d'un bloc finally car endTime ne sera pas utilisé si une exception est levée.
Peter Lawrey
197

Je pars avec la réponse simple. Travaille pour moi.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

Cela fonctionne plutôt bien. La résolution n'est évidemment qu'à la milliseconde, vous pouvez faire mieux avec System.nanoTime (). Il y a quelques limitations aux deux (tranches de planification du système d'exploitation, etc.) mais cela fonctionne plutôt bien.

Moyenne sur quelques courses (le plus sera le mieux) et vous aurez une idée décente.

MBCook
la source
51
En fait, System.currentTimeMillis () n'est précis qu'au-dessus de 15 ms. Pour des valeurs vraiment basses, on ne peut pas lui faire confiance. La solution pour cela (comme mentionné) est System.nanoTime ();
Steve g
Ok, j'étais sur le point d'accepter cela comme réponse officielle jusqu'à ce que je lise le commentaire de Steve g. Bon morceau, Steve!
Ogre Psalm33
4
nanoTime () ne garantit pas une précision meilleure que currentTimeMillis, mais de nombreuses implémentations JVM ont une meilleure précision avec nanoTime.
James Schek
5
@JamesSchek Vous avez vraiment besoin de regarder votre formulation, comme je l'ai déjà mentionné ailleurs pour ce commentaire identique; nanoTimeest garanti au moins aussi résolu que currentTimeMillis. docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy
Le seul avantage léger currentTimeMillisest qu'il s'agit d'un horodatage réel, et pourrait également être utilisé pour enregistrer les heures de début / fin, alors que nanoTime"ne peut être utilisé que pour mesurer le temps écoulé et n'est lié à aucune autre notion de système ou d'horloge murale. . "
Brad Parks
177

Allez les gars! Personne n'a mentionné la manière Guava de faire cela (ce qui est sans doute génial):

import com.google.common.base.Stopwatch;

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

La bonne chose est que Stopwatch.toString () fait un bon travail de sélection des unités de temps pour la mesure. C'est-à-dire que si la valeur est petite, elle produira 38 ns, si elle est longue, elle affichera 5m 3s

Encore plus agréable:

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

Remarque: Google Guava nécessite Java 1.6+

Dmitry Kalashnikov
la source
21
Malheureusement, le chronomètre de Guava n'est pas thread-safe. Je l'ai appris à la dure.
Dexter Legaspi
6
@DexterLegaspi Serait très intéressé par votre expérience! Se soucier de partager?
Siddhartha
1
L'utilisation du chronomètre en parallèle vous obligerait à appeler start()plusieurs fois de suite (pareil pour stop()).
Mingwei Samuel
141

En utilisant Instant et Duration à partir de la nouvelle API de Java 8,

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

les sorties,

PT5S
Soufiyan Ghori
la source
2
Merci, comment puis-je produire le résultat sans avoir le PT devant?
java123999
1
Le problème avec la méthode est qu'Instant ne pose pas de problème de précision en milli et nano seconde. Ref: stackoverflow.com/questions/20689055/…
prashantsunkari
8
@ java123999: Vous pouvez appeler Duration.between(start, end).getSeconds(). Durationa également des méthodes pour convertir en d'autres unités de temps, par exemple toMillis()qui convertit en millisecondes.
Emil Lunde
100

Rassemblé toutes les façons possibles en un seul endroit.

Date

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

Système. 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 ) );

Format lisible par l'homme

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

Goyave: Google Stopwatch JAR «Le chronomètre a pour objet de mesurer le temps écoulé en nanosecondes.

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 fournit une API pratique pour les timings.

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 Java date time de Java 8 «Un objet Duration représente une période de temps entre deux objets 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 fournit laclasse utilitaire StopWatch pour mesurer le temps écoulé 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());
}

Production:

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
la source
Le chronomètre de Guava, Apache Commons et Spring Framework ne sont pas thread-safe. Non sûr pour une utilisation en production.
Deepak Puthraya
@DeepakPuthraya alors quelle bibliothèque utiliser qui est sûre pour une utilisation en production?
gaurav
1
@DeepakPuthraya vous pouvez utiliser l'API Java date-time fournie avec java 8. C'est simple.
Yash
IMO ce poste bénéficierait si chaque solution montrait également la sortie des sorties du système.
BAERUS
87

Utilisez un profileur (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler, etc.). Vous obtiendrez les résultats les plus précis et le moins intrusif. Ils utilisent le mécanisme JVM intégré pour le profilage qui peut également vous fournir des informations supplémentaires telles que les traces de pile, les chemins d'exécution et des résultats plus complets si nécessaire.

Lorsque vous utilisez un profileur entièrement intégré, il n'est pas facile de profiler une méthode. Clic droit, Profiler -> Ajouter aux méthodes racine. Exécutez ensuite le profileur comme si vous faisiez un test ou un débogueur.

James Schek
la source
C'était aussi une excellente suggestion, et l'un de ces moments "duh" pour moi quand j'ai lu cette réponse. Notre projet utilise JDeveloper, mais j'ai vérifié, et bien sûr, il a un profileur intégré!
Ogre Psalm33
2
De java 7 build 40 (je pense), ils incluaient l'ancien JRockits Flight Recorder à java (recherche de Java Mission Control)
Niels Bech Nielsen
Bien sûr, @NielsBechNielsen! oracle.com/technetwork/java/javaseproducts/mission-control/…
Ogre Psalm33
Comment obtenir l'exécution d'une méthode en Java par Visual VM, par exemple?
okwap
41

Ce n'est probablement pas ce que vous vouliez que je dise, mais c'est une bonne utilisation d'AOP. Fouettez un intercepteur proxy autour de votre méthode et faites le timing.

Le quoi, pourquoi et comment de l'AOP dépasse malheureusement la portée de cette réponse, mais c'est comme ça que je le ferais probablement.

Edit: Voici un lien vers Spring AOP pour vous aider à démarrer, si vous le souhaitez. Il s'agit de l'implémentation la plus accessible d'AOP rencontrée par Iive pour Java.

De plus, étant donné les suggestions très simples de tout le monde, je dois ajouter que l'AOP est pour quand vous ne voulez pas que des choses comme le timing envahissent votre code. Mais dans de nombreux cas, ce type d'approche simple et facile convient.

skaffman
la source
3
Voici un tutoriel sur la façon de procéder avec Spring: veerasundar.com/blog/2010/01/…
David Tinker
39

System.currentTimeMillis();N'EST PAS une bonne approche pour mesurer les performances de vos algorithmes. Il mesure le temps total que vous vivez en tant qu'utilisateur regardant l'écran de l'ordinateur. Il inclut également le temps consommé par tout le reste exécuté sur votre ordinateur en arrière-plan. Cela pourrait faire une énorme différence si vous avez beaucoup de programmes en cours d'exécution sur votre poste de travail.

L'approche appropriée consiste à utiliser le java.lang.managementpackage.

Depuis le site http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking :

  • Le "temps utilisateur" est le temps passé à exécuter le code de votre application.
  • "Heure système" est le temps passé à exécuter le code du système d'exploitation au nom de votre application (comme pour les E / S).

getCpuTime() méthode vous donne la somme de ceux-ci:

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
la source
4
C'est certainement un bon point, que le "temps utilisateur" (temps d'horloge murale) n'est pas toujours une grande mesure des performances, en particulier dans un programme multi-thread.
Ogre Psalm33
C'est la réponse que je cherche.
ZhaoGang
30

Avec Java 8, vous pouvez également faire quelque chose comme ça avec toutes les méthodes normales :

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

avec TimeIt comme:

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

Avec cette méthode, vous pouvez facilement mesurer le temps n'importe où dans votre code sans le casser. Dans cet exemple simple, j'imprime simplement l'heure. Pouvez-vous ajouter un commutateur pour TimeIt, par exemple pour imprimer uniquement l'heure dans DebugMode ou quelque chose.

Si vous travaillez avec Function, vous pouvez faire quelque chose comme ceci:

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
la source
Cela semble beaucoup mieux que d'autres solutions. C'est plus proche du Spring AOP mais plus léger que ça. True java 8 way! +1 Merci!
Amit Kumar
Peut-être que cela vous semble bien, car Stefan utilise de nouvelles fonctions java fantaisistes. Mais je pense que c'est difficile à lire et à comprendre.
Stimpson Cat
18

Nous pouvons également utiliser la classe StopWatch de communs Apache pour mesurer le temps.

Exemple de code

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
la source
15

Juste une petite torsion, si vous n'utilisez pas d'outillage et que vous souhaitez chronométrer des méthodes avec un temps d'exécution faible: exécutez-le plusieurs fois, chaque fois en doublant le nombre d'exécutions jusqu'à ce que vous atteigniez une seconde environ. Ainsi, l'heure de l'appel à System.nanoTime et ainsi de suite, ni la précision de System.nanoTime n'affecte beaucoup le résultat.

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

Bien sûr, les mises en garde sur l' utilisation de l'horloge murale appliquent: influences de JIT-compilation, plusieurs threads / processus , etc. Ainsi, vous devez d'abord exécuter la méthode beaucoup de temps d' abord, de telle sorte que le compilateur JIT fait son travail, puis répétez ce test plusieurs fois et prenez le temps d'exécution le plus bas.

Hans-Peter Störr
la source
13

Nous utilisons à cet effet des annotations AspectJ et Java. Si nous avons besoin de connaître le temps d'exécution d'une méthode, nous l'annotons simplement. Une version plus avancée pourrait utiliser un niveau de journal propre qui peut être activé et désactivé au moment de l'exécution.

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

la source
13

JEP 230: Microbenchmark Suite

Pour info, JEP 230: Microbenchmark Suite est un projet OpenJDK pour:

Ajoutez une suite de base de microbenchmarks au code source JDK et aidez les développeurs à exécuter facilement les microbenchmarks existants et à en créer de nouveaux.

Cette fonctionnalité est arrivée dans Java 12 .

Harnais Java Microbenchmark (JMH)

Pour les versions antérieures de Java, jetez un œil au projet Java Microbenchmark Harness (JMH) sur lequel JEP 230 est basé.

Basil Bourque
la source
11

Vraiment un bon code.

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
la source
3
En fait, la question était de savoir comment calculer le temps nécessaire à une méthode, pas comment la formater. Cependant cette question est assez ancienne (presque quatre ans!). Essayez d'éviter de ressusciter les anciens threads à moins que la réponse n'ajoute quelque chose de nouveau et de significatif aux réponses existantes.
Leigh
1
Et pour ajouter les millis restants à la fin, apportez les modifications suivantes: 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

Vous pouvez utiliser Perf4j . Utilitaire très cool. L'utilisation est simple

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

Plus d'informations peuvent être trouvées dans le Guide du développeur

Edit: Le projet semble mort

mergenchik
la source
1
Perf4j peut également générer de belles statistiques .
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
la source
1
Rouler votre propre classe simple est un bon choix lorsque vous avez déjà configuré le système de construction et les OTS dépendants, et que vous ne voulez pas vous soucier de tirer dans un autre package OTS qui comprend une classe de temporisateur utilitaire.
Ogre Psalm33
7

Je fais essentiellement des variations de cela, mais compte tenu du fonctionnement de la compilation des points d'accès, si vous voulez obtenir des résultats précis, vous devez jeter les premières mesures et vous assurer que vous utilisez la méthode dans une application du monde réel (lire l'application spécifique).

Si le JIT décide de le compiler, vos chiffres varieront considérablement. alors soyez conscient

luke
la source
7

En utilisant AOP / AspectJ et l' @Loggableannotation 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é à l'installation de consignation SLF4J avec DEBUGniveau de consignation. Et chaque message de journal inclura le temps d'exécution.

yegor256
la source
7

Spring fournit une classe utilitaire org.springframework.util.StopWatch , selon JavaDoc:

Chronomètre simple, permettant de chronométrer un certain nombre de tâches, exposant le temps d'exécution total et le temps d'exécution pour chaque tâche nommée.

Usage:

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

Production:

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

Avec Aspects:

@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
la source
Est-il possible de l'utiliser avec AspectJ?
zygimantus
7

J'ai écrit une méthode pour imprimer le temps d'exécution de la méthode sous une forme très lisible. Par exemple, pour calculer la factorielle de 1 million, cela prend environ 9 minutes. Ainsi, le temps d'exécution est imprimé comme:

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

Le code est ici:

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
la source
6

Il y a plusieurs façons de procéder. Je reviens normalement à utiliser simplement quelque chose comme ça:

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

ou la même chose avec System.nanoTime ();

Pour quelque chose de plus sur le côté de l'analyse comparative, il semble également y avoir celui-ci: http://jetm.void.fm/ Je n'ai jamais essayé cependant.

Horst Gutmann
la source
6

Vous pouvez utiliser la bibliothèque de métriques qui fournit divers instruments de mesure. Ajouter une dépendance:

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

Et configurez-le pour votre environnement.

Les méthodes peuvent être annotées avec @Timed :

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

ou un morceau de code enveloppé avec Timer :

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

Les métriques agrégées peuvent être exportées vers la console, JMX, CSV ou autre.

@Timed exemple de sortie de mesures:

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
Tout comme
la source
5

Si vous voulez une horloge murale

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

Comme l'a dit "skaffman", utilisez AOP OU vous pouvez utiliser le tissage de bytecode d'exécution, tout comme les outils de couverture de méthode de test unitaire utilisent pour ajouter de manière transparente des informations de synchronisation aux méthodes invoquées.

Vous pouvez consulter le code utilisé par les outils open source comme Emma ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ). L'autre outil de couverture open source est http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download .

Si vous parvenez finalement à faire ce que vous avez prévu, veuillez. partagez-le avec la communauté ici avec vos tâches / pots de fourmis.

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

J'ai modifié le code de la bonne réponse pour obtenir le résultat en quelques secondes:

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
la source
4

Vous pouvez utiliser la classe chronomètre du projet Spring Core:

Code:

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

Documentation pour le chronomètre: chronomètre simple, permettant de chronométrer un certain nombre de tâches, exposant le temps d'exécution total et le temps d'exécution pour chaque tâche nommée. Dissimule l'utilisation de System.currentTimeMillis (), améliorant la lisibilité du code d'application et réduisant la probabilité d'erreurs de calcul. Notez que cet objet n'est pas conçu pour être thread-safe et n'utilise pas la synchronisation. Cette classe est normalement utilisée pour vérifier les performances lors de la validation de concepts et lors du développement, plutôt que dans le cadre d'applications de production.

praveen jain
la source
3

Vous pouvez essayer de cette façon si vous voulez juste connaître l'heure.

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

Ok, c'est une classe simple à utiliser pour un simple timing simple de vos fonctions. Il y a un exemple en dessous.

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

Exemple d'utilisation:

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

Exemple de sortie de console:

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

Dans Java 8, une nouvelle classe nommée Instantest introduite. Selon doc:

Instant représente le début d'une nanoseconde sur la ligne de temps. Cette classe est utile pour générer un horodatage pour représenter le temps machine. La portée d'un instant nécessite le stockage d'un nombre supérieur à un long. Pour y parvenir, la classe stocke un long représentant des époques-secondes et un int représentant des nanosecondes de secondes, qui seront toujours compris entre 0 et 999 999 999. Les secondes-époques sont mesurées à partir de l'époque Java standard de 1970-01-01T00: 00: 00Z où les instants après l'époque ont des valeurs positives et les instants précédents ont des valeurs négatives. Pour les parties d'époque seconde et de nanoseconde, une valeur plus grande est toujours plus tardive sur la ligne temporelle qu'une valeur plus petite.

Cela peut être utilisé comme:

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

Il imprime PT7.001S.

akhil_mittal
la source