Mesurer le temps écoulé en Java

1. Vue d'ensemble

Dans cet article, nous allons voir comment mesurer le temps écoulé en Java. Bien que cela puisse sembler facile, il y a quelques écueils dont nous devons être conscients.

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 une exigence pour mesurer le temps écoulé en Java, nous pouvons essayer de le faire comme:

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

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

Cependant, le résultat peut et sera inexact car System.currentTimeMillis () mesure l' heure de l' horloge murale . L'heure de l'horloge murale peut changer pour de nombreuses raisons, par exemple, 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 classe java.lang.System est nanoTime () . Si nous regardons la documentation Java, 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 qu'avant. La seule différence est la méthode utilisée pour obtenir les horodatages - nanoTime () au lieu de currentTimeMillis () .

Notons également que nanoTime () 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 avec nanoTime () est que même s'il fournit une précision nanoseconde, il ne garantit pas une résolution nanoseconde (c'est-à-dire à quelle fréquence la valeur est mise à jour).

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

3. Java 8

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

3.1. Échelle de temps Java

La manière traditionnelle de mesurer le temps est de diviser une journée en 24 heures de 60 minutes de 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 fait à 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 reste alignée sur le Soleil.

L'échelle de temps Java divise chaque jour calendaire en exactement 86 400 subdivisions, appelées secondes . Il n'y a pas de seconde intercalaire.

3.2. Classe instantanée

La classe Instant représente un instant sur la chronologie. Fondamentalement, il s'agit d'un horodatage numérique depuis l'époque Java standard de 1970-01-01T00: 00: 00Z .

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

Nous pouvons stocker les heures de début et de fin dans deux variables, comme dans les exemples précédents. Ensuite, nous pouvons calculer le temps écoulé entre les deux instants.

Nous pouvons également utiliser la classe Duration et sa méthode between () pour obtenir la durée entre deux objets Instant . Enfin, nous devons convertir la durée en millisecondes:

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

4. Chronomètre

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

4.1. Dépendance de Maven

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

 org.apache.commons commons-lang3 3.7 

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

4.2. Mesure du temps écoulé avec StopWatch

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éthode stop () . Enfin, pour obtenir le résultat réel, nous appelons getTime () :

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

StopWatch a quelques méthodes d'aide supplémentaires que nous pouvons utiliser pour suspendre ou reprendre notre mesure. Cela peut être utile si nous devons rendre notre référence 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 couvert une manière très «traditionnelle» (et inexacte) en utilisant currentTimeMillis () . De plus, nous avons vérifié StopWatch d' Apache Common et examiné les nouvelles classes disponibles dans Java 8.

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

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 l'avons exploré ici.

Enfin, comme toujours, le code utilisé lors de la discussion se trouve à l'adresse over sur GitHub.