Net 2.0 : StopWatch, ou le temps qui passe

Ronald VASSEUR

Lorsque vous réalisez des applications, vous avez souvent plusieurs voies possibles pour effectuer une opération, au-delà des aspects de sécurité et de fiabilité, l'aspect de la performance est à prendre en compte. La manière la plus évidente de mesurer la performance de votre code est en fait de regarder son temps d'exécution…

- Titre : Net 2.0 : StopWatch, ou le temps qui passe

- Auteur : Ronald VASSEUR

- Parution : 30 janvier 2006

- Mise à jour : 28 février 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2006 Ronald Vasseur. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Introduction

- I. Présentation de la classe StopWatch

- I-A. Les méthodes

- I-B. Les propriétés

- II. Mesurer le temps d'exécution d'une méthode

- III. Mesurer le temps d'exécution cumulé de plusieurs méthodes

- IV. Une miniapplication exemple

- Conclusion

- V. Ressources

Introduction

Avant le Framework .Net en version 2.0, il pouvait être assez compliqué de mesurer précisément un temps d'exécution. Avec .Net, tout ceci est désormais terminé, en effet, une nouvelle classe StopWatch propose de nous rendre ce service avec une précision remarquable, de l'ordre de la microseconde (0,000 001 seconde). Voyons de plus près et sans plus tarder cette classe.

.Net 2.0

I - Présentation de la classe StopWatch

Le Framework .Net 2.0, dans sa multitude de nouvelles classes, nous apporte ce que l'on pourrait considérer comme une petite classe, mais il faut bien le reconnaître d'une très grande utilité pour les développeurs que nous sommes. La classe StopWatch, c'est son nom, faisant partie du namespace System.Diagnostics, nous offre des méthodes permettant de mesurer très précisément (de l'ordre de la microseconde) le temps d'exécution de notre code, et cela sans effort aucun, je serais tenté de dire trivialement « plus simple que cela tu meurs ». Voici les méthodes et les propriétés principales que vous devez connaître.

I-A - Les méthodes

Nom

Description

Start()

démarre le chronomètre qui mesure l'intervalle de temps entre le « Start » et le « Stop ». Le Start() peut aussi être utilisé pour relancer un chronomètre qui a déjà été stoppé par un Stop() dans le cas de mesures cumulées.

Stop()

arrête le chronomètre qui mesure l'intervalle depuis le Start().

Reset()

remise à zéro du temps déjà écoulé sur le chronomètre.

StartNew()

instancie une nouvelle instance de l'objet StopWatch avec la propriété Elapsed à 0.

I-B - Les propriétés

Nom

Description

Elapsed

Temps total (sous la forme d'un TimeSpan) écoulé mesuré par l'instance courante de l'objet StopWatch.

ElapsedMilliseconds

Temps total écoulé en millisecondes mesuré par l'instance courante l'objet StopWatch.

ElapsedTicks

Nombre total de « timer ticks » mesurés par l'instance courante l'objet StopWatch.

IsRunning

Booléen qui détermine si l'instance courante de StopWatch est active, c'est-à-dire si elle est en train de mesurer un intervalle.

Après avoir vu les méthodes et propriétés principales de StopWatch, étudions un petit exemple nous permettant de mesurer le temps d'exécution d'une méthode toute simple…

II - Mesurer le temps d'exécution d'une méthode

Voici un exemple simple qui montre comment mesurer le temps d'exécution d'une méthode, pour cela il va nous falloir utiliser une instance de StopWatch, ses deux méthodes Start() et Stop() et sa propriété ElapsedMilliseconds qui va nous donner un résultat en millisecondes, choix qui est ici pertinent, puisque le résultat attendu sera de quelques millisecondes. Si vous souhaitiez mesurer des temps d'exécution plus longs pour des raisons concrètes de lisibilité, il serait peut-être plus judicieux d'utiliser par exemple la propriété Elapsed qui vous fournit un TimeSpan, et non pas un entier (Long) comme ElapsedMillisecondes.

Remarque : la classe StopWatch appartient au namespace System. Diagnostics, il vous faut donc penser à le signaler dans l'entête de votre classe, comme vous pouvez le voir ci-dessous.

Using pour C#

using System.Diagnostics

Imports pour Visual Basic .Net

Imports System.Diagnostics

Voici les deux fonctions dont le temps d'exécution va être mesuré par StopWatch, j'ai volontairement choisi des exemples simplistes, le but étant ici de démontrer comment mesurer un temps d'exécution facilement.

Fonctions de test

' Fonction de test qui concatène 20000 caractères grâce à la classe StringBuilder
Private Function test1() As Boolean

Dim i As Integer
Dim strB As New StringBuilder

' Boucle de concaténation de caractères
For i = 0 To 20000
strB.Append("d")
Next

strB.ToString()

Return True

End Function

' Fonction de test qui concatène 20000 caractères grâce à la classe String
Private Function test2() As Boolean

Dim i As Integer
Dim str As String = Nothing

' Boucle de concaténation de caractères
For i = 0 To 20000
str &= "d"
Next

Return True

End Function

Voici maintenant le code du bouton permettant d'instancier l'objet StopWatch, puis d'effectuer la mesure du temps d'exécution, ici je déclenche le chrono juste avant l'appel de la fonction, et l'arrête immédiatement après qu'elle s'est terminée.

Mesure du temps d'exécution

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

' Instanciation d'un objet StopWatch
Dim monSWtest1 As New Stopwatch

' Déclenchement du "chronomètre"
monSWtest1.Start()
' Lancement de la fonction de test
test1()
' Arrêt du "chronomètre"
monSWtest1.Stop()

' Récupération et affichage du temps écoulé
Label1.Text = monSWtest1.ElapsedMilliseconds.ToString & " milliseconde(s)"

End Sub

De par la nature même de la technologie .Net, il vous faut exécuter au moins une fois la mesure pour que par la suite vous puissiez obtenir un résultat fiable, en effet, lors du premier appel d'une méthode le code MSIL de l'assembly est compilé par le compilateur JIT, ce n'est donc qu'au deuxième appel que la « performance réelle » du code est mesurée. De plus, mais comme pour tout test qui se respecte, pour avoir des résultats fiables il ne faut pas hésiter à multiplier les essais pour se voir dégager une valeur moyenne, en effet une machine ne présente pas un taux de charge et de disponibilité continu.

III - Mesurer le temps d'exécution cumulé de plusieurs méthodes

Il est possible de mesurer l'exécution cumulée de plusieurs méthodes, pour cela il suffit d'arrêter le « chronomètre » puis de le relancer pour la méthode suivante, sans bien entendu le réinitialiser entre-temps. Vous pouvez ainsi réaliser des mesures de manière aisée et souple, et même si cela peut apparaître « gadget » au premier abord, à l'usage cela devient un outil 'inutile' donc totalement indispensable ! :)

Code permettant d'effectuer une mesure d'exécutions cumulées

Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click

' Instanciation d'un objet StopWatch
Dim monSWcumul As New Stopwatch

' Déclenchement du "chronomètre"
monSWcumul.Start()
' Lancement de la fonction de test
test2()
' Arrêt du "chronomètre"
monSWcumul.Stop()
' Le chronomètre est relancé et reprend là où il avait été arrêté
monSWcumul.Start()
' Lancement pour la seconde fois de la fonction de test
test2()
' Arrêt du "chronomètre"
monSWcumul.Stop()

' Récupération et affichage du temps écoulé
Label3.Text = monSWcumul.ElapsedMilliseconds.ToString & " milliseconde(s)"

End Sub

IV - Une miniapplication exemple

Pour illustrer tout cela et avoir un exemple fonctionnel, j'ai réalisé une miniapplication qui permet de mesurer le temps d'exécution de méthodes, dans différentes configurations comme nous l'avons vu au long de cet article. Vous verrez qu'il n'y a rien d'extraordinaire dans ce programme, juste de quoi démontrer le principe de base.

Remarque : j'ai réalisé cette application en Visual Basic .Net, mais vous pouvez très facilement convertir le code en C# grâce au convertisseur de Developpez.com, ou même à la main, car il n'y a pas de code complexe.

Voici une capture d'écran de cette miniapplication :

Application exemple.

Comme vous le voyez cette application permet de comparer le temps pris par une concaténation de 20 000 caractères, et cela avec une String classique, et avec un StringBuilder, qui vous vous en doutez déjà sera bien plus performant.

L'exécutable ainsi que les sources (Solution Visual Studio 2005) de cette miniapplication sont disponibles en téléchargement dans la rubrique « Ressources » de cet article.

Conclusion

Vous avez pu voir, par le biais de cet article, qu'il n'y a rien de révolutionnaire, mais tout de même, cette classe StopWatch est quand même une nouveauté très intéressante de la version 2.0 du Framework .Net, en effet, lors de développement, on peut être amené à vouloir estimer la performance de son code ou encore choisir entre plusieurs possibilités. Avant pour mesurer un temps d'exécution, il fallait soit créer soit même, soit utiliser le peu de solutions existantes dans le Framework, qui de plus, étaient trop imprécises et rigides. N'oubliez pas qu'ici la précision est de l'ordre de la microseconde.

Cette petite classe trouvera donc tout un tas d'applications différentes, celle qui me semble personnellement la plus intéressante est la mesure du temps d'exécution de méthodes dans une optique d'évaluation des performances, cependant je suis sûr que chacun d'entre vous aura une très bonne raison d'utiliser cette nouvelle classe. Merci d'avoir pris le temps de lire tout ceci, et rendez-vous bientôt pour un nouvel article.

V - Ressources

- Projet Visual Studio 2005 (VB.Net) (98 Ko) : Cliquez ici

- Miniapplication de mesure de temps d'exécution (7 Ko) : Cliquez ici

- Le namespace System.Diagnostics : Cliquez ici

- La classe StopWatch : Cliquez ici

- La classe StringBuilder : Cliquez ici

Un très grand merci à Freegreg pour la relecture de cet article.