Mesurer le temps écoulé en Java

Mesurer le temps écoulé en Java

1. Vue d'ensemble

Dans cet article, nous allons voir comment mesurer le temps écoulé en Java. While this may sound easy, there’re a few pitfalls that we must be aware of.

Nous explorerons les classes Java standard et les packages externes qui fournissent des fonctionnalités pour mesurer le temps écoulé.

2. Mesures simples

2.1. currentTimeMillis()

Lorsque nous rencontrons un besoin de mesurer le temps écoulé en Java, nous pouvons essayer de le faire comme suit:

long start = System.currentTimeMillis();
// ...
long finish = System.currentTimeMillis();
long timeElapsed = finish - start;

Si nous examinons le code, cela est parfaitement logique. Nous obtenons un horodatage au début et un autre lorsque le code est terminé. Le temps écoulé est la différence entre ces deux valeurs.

Cependant, l'heure de l'horloge muralethe result may and will be inaccurate as System.currentTimeMillis() measures wall-clock time. peut changer pour de nombreuses raisons, par ex. changer l'heure du système peut affecter les résultats ou une seconde intercalaire perturbera le résultat.

2.2. nanoTime()

Une autre méthode de la classejava.lang.System estnanoTime(). Si nous regardons lesJava documentation, nous trouverons l'instruction suivante:

"Cette méthode ne peut être utilisée que pour mesurer le temps écoulé et n'est liée à aucune autre notion de temps système ou d'horloge murale."

Utilisons-le:

long start = System.nanoTime();
// ...
long finish = System.nanoTime();
long timeElapsed = finish - start;

Le code est fondamentalement le même que précédemment. La seule différence est la méthode utilisée pour obtenir les horodatages -nanoTime() au lieu decurrentTimeMillis().

Notons également quenanoTime() renvoie évidemment le temps en nanosecondes. Par conséquent, si le temps écoulé est mesuré dans une unité de temps différente, nous devons le convertir en conséquence.

Par exemple, pour convertir en millisecondes, nous devons diviser le résultat en nanosecondes par 1.000.000.

Un autre piège avecnanoTime() est queeven though it provides nanosecond precision, it doesn’t guarantee nanosecond resolution (i.e. combien de fois la valeur est mise à jour).

Cependant, cela garantit que la résolution sera au moins aussi bonne que celle decurrentTimeMillis().

3. Java 8

Si nous utilisons Java 8, nous pouvons essayer les nouvelles classesjava.time.Instant etjava.time.Duration. Les deux sont immuables, thread-safe et utilisent leur propre échelle de temps, lesJava Time-Scale, comme toutes les classes de la nouvelle APIjava.time.

3.1. Échelle de temps Java

La manière traditionnelle de mesurer le temps consiste à diviser une journée en 24 heures, soit 60 minutes, soit 60 secondes, ce qui donne 86,400 secondes par jour. Cependant, les journées solaires ne sont pas toujours aussi longues.

L'échelle de temps UTC permet en réalité à un jour d'avoir 86,399 ou 86,401 secondes SI. Une seconde SI est une «seconde internationale standard» scientifique et est définie par des périodes de rayonnement de l'atome de césium 133). Ceci est nécessaire pour que la journée soit alignée avec le soleil.

The Java Time-Scale divides each calendar day into exactly 86.400 subdivisions, known as seconds. Il n'y a pas de secondes intercalaires.

3.2. ClasseInstant

La classeInstant représente un instant sur la timeline. Fondamentalement, il s'agit d'un horodatage numérique depuis l'époque Java standard de1970-01-01T00:00:00Z.

Afin d'obtenir l'horodatage actuel, nous pouvons utiliser la méthode statique deInstant.now(). Cette méthode permet de passer un paramètre optionnelClock. S'il est omis, il utilise l'horloge système dans le fuseau horaire par défaut.

We can store start and finish times in two variables, as in previous examples. Ensuite, nous pouvons calculer le temps écoulé entre les deux instants.

Nous pouvons en outre utiliser la classeDuration et la méthodebetween() pour obtenir la durée entre deux objetsInstant. Enfin, nous devons convertirDuration en millisecondes:

Instant start = Instant.now();
// CODE HERE
Instant finish = Instant.now();
long timeElapsed = Duration.between(start, finish).toMillis();

4. StopWatch

Passant aux bibliothèques, Apache Commons Lang fournit la classeStopWatch qui peut être utilisée pour mesurer le temps écoulé.

4.1. Dépendance Maven

Nous pouvons obtenir la dernière version en mettant à jour le fichier pom.xml:


    org.apache.commons
    commons-lang3
    3.7

La dernière version de la dépendance peut être vérifiéehere.

4.2. Mesure du temps écoulé avecStopWatch

Tout d'abord, nous devons obtenir une instance de la classe et ensuite nous pouvons simplement mesurer le temps écoulé:

StopWatch watch = new StopWatch();
watch.start();

Une fois que nous avons une montre en cours d'exécution, nous pouvons exécuter le code que nous voulons comparer, puis à la fin, nous appelons simplement la méthodestop(). Enfin, pour obtenir le résultat réel, nous appelonsgetTime():

watch.stop();
System.out.println("Time Elapsed: " + watch.getTime()); // Prints: Time Elapsed: 2501

StopWatch has a few additional helper methods that we can use in order to pause or resume our measurement. Cela peut être utile si nous devons rendre notre benchmark plus complexe.

Enfin, notons que la classe n'est pas thread-safe.

5. Conclusion

Il existe de nombreuses façons de mesurer le temps en Java. Nous avons abordé une manière très «traditionnelle» (et inexacte) en utilisantcurrentTimeMillis(). De plus, nous avons vérifié lesStopWatch d'Apache Common et examiné les nouvelles classes disponibles dans Java 8.

Globalement, pour des mesures simples et correctes du temps écoulé, la méthodenanoTime() est suffisante. Il est également plus court à taper quecurrentTimeMillis().

Notons, cependant, que pour un bon benchmarking, au lieu de mesurer le temps manuellement, nous pouvons utiliser un framework comme le Java Microbenchmark Harness (JMH). Ce sujet dépasse le cadre de cet article, mais nous avons exploréit here.

Enfin, comme toujours, le code utilisé lors de la discussion se trouveover on GitHub.