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.000001 seconde). Voyons de plus près et sans plus tarder cette classe.

Image non disponible
.Net 2.0

1. 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 serai 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 :

1.1. 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 utiliser 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.

1.2. 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…

2. 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#
Sélectionnez

using System.Diagnostics
Imports pour Visual Basic .Net
Sélectionnez

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 içi de démontrer comment mesurer un temps d'exécution facilement.

Fonctions de test
Sélectionnez

    ' 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 soit terminée.

Mesure du temps d'exécution
Sélectionnez

   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 puissez 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 comppilateur JIT, ce n'est donc qu'au deuxième appel que la "performance réelle" du code est mesuré. 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é continue.

3. 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 simplement 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
Sélectionnez

    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 reprends   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

4. Une mini application exemple

Pour illustrer tout cela et avoir un exemple fonctionnel, j'ai réalisé une mini-application 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 à rien de 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 mini-application :

Image non disponible
Application exemple.

Comme vous le voyez cette application permet de comparer le temps pris par une concaténation de 20000 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 mini-application 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 à 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.

C. Ressources



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