|
Site |
Cours VB.net |
|
|
|
Chronométrer le code. |
|
|
On veut comparer 2 routines et savoir laquelle est la plus rapide.
On peut pour compter le temps écoulé:
Utiliser un Timer
Utiliser l'heure système
Utiliser la Classe Environment.Tickcount
Appeler QueryPerformanceCounter, une routine de Kernel32
Utiliser System.Diagnostics.Stopwatch (Framework 2 Vb 2005)
Pour chronométrer une évènement long.
Entendons par évènement long, plusieurs secondes ou minutes.
3 solutions:
- On utilise un Timer, (dans l'évènement Ticks qui survient toutes les secondes, une variable s'incrémente comptant les secondes).(4-5).
- On peut utiliser l'heure Système.
Dim Debut, Fin As DateTime
Dim Durée As TimeSpan
Debut=Now
...Routine...
Fin=Now
Durée=Fin-Debut
(Utiliser Durée.ToString pour afficher)
- On peut utiliser la variable Environment.tickcount()
Debut=Environment.tickcount()
...Routine...
Fin=Environment.tickcount()
Créer un compteur pour les temps très court (Framework 1 , VB2003).
C'est le cas pour chronométrer des routines de durée bien inférieure à une seconde.
Cela semblait à première vue facile!!!
J'ai en premier lieu utilisé un Timer, (dans l'évènement Ticks un compteur de temps s'incrémente) mais les intervalles de déclenchement semblent longs et aléatoires.
J'ai ensuite utilisé l'heure système:
Mais 'Durée' est toujours égal à 0 pour les routines rapides car il semble que Now ne retourne pas les millisecondes ou les Ticks.
J'ai trouvé la solution chez Microsoft:
Utilisation d'une routine de Kernel32 qui retourne la valeur d'un compteur (QueryPerformanceCounter).
De plus QueryPerformanceFrequency retourne le nombre de fois que le compteur tourne par seconde.
Exemple: comparer 2 boucles, l'une contenant une affectation de variable tableau (b=a(2)) l'autre une affectation de variable simple (b=c), on gagne 33%.
Declare
Function QueryPerformanceCounter Lib "Kernel32" (ByRef X As Long) As ShortDeclare Function QueryPerformanceFrequency Lib "Kernel32" (ByRef X As Long) As Short
Private
Sub ButtonGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonGo.Click Dim debut As Long Dim fin As Long Dim i As Long Dim a(5) As String Dim b As String Dim c As String Dim d1 As Long Dim d2 As Long '**********première routineQueryPerformanceCounter(debut)
For i = 0 To 10000b = a(2)
NextQueryPerformanceCounter(fin)
d1 = fin - debut
Label1.Text = d1.ToString
'**********seconde routineQueryPerformanceCounter(debut)
c = a(2)
For i = 0 To 10000b = c
NextQueryPerformanceCounter(fin)
d2 = fin - debut
Label2.Text = d2.ToString
Label5.Text = "Gain 2eme routine:" & 100 - Int(d2 / d1 * 100).ToString
End SubC'est cette routine qui est utilisée pour étudier l'optimisation du code.
Elle n'est pas parfaite, car sujette à variation: les valeurs sont différentes d'un essai à l'autre en fonction des processus en cours !
C'est pourquoi la seule façon fiable de faire des tests consiste à avoir une approche expérimentale : on répète la mesure un certain nombre de fois et on fait une moyenne des essais individuels.
Pour des routines très très rapides, une autre façon de faire consiste à effectuer des tests sur de longues durées (en répétant des milliers de fois la routine rapide à l'aide d'une boucle)pour arriver à des temps de plusieurs dizaines de secondes, de manière à diluer les interventions de Windows dans le processus.
Il y a peut-être d'autres solutions?
Créer un compteur pour les temps très court (Framework 2 , VB2005)
Le Framework 2.0 comporte une classe qui encapsule l'utilisation de l' API QueryPerformanceCounter: System.Diagnostics.Stopwatch.
Dim Stopwatch As System.Diagnostics.stopWatch = System.Diagnostics.Stopwatch.StartNew()
' Code à mesurer
Debug.WriteLine(stopWatch.ElapsedMilliseconds.ToString())
La première ligne crée une instance d'un
Stopwatch et démarre le compteur.
La propriété ElapsedMilliseconds nous donne le
temps mesuré en millisecondes.
On a également la propriété ElapsedTicks pour
compter les Ticks (1 Ticks: 100 nanosecondes).
Enfin si l'on veut compter en TimeSpan, utilisons la propriété
Elapsed.
On peut arrêter et redémarrer le compteur plusieurs fois.
stopwatch.Stop 'arrête le compteur
stopwatch.Start 'fait redémarrer le compteur
stopwatch.Reset() 'remet le compteur à zéro
|
|
|
|
|