#36: Calcolare il tempo di esecuzione di un frammento di codice (VB.NET)
Pubblicato da Mario De Ghetto su 12 Giugno 2008
Sviluppando o studiando una nuova tecnica, in un qualsiasi linguaggio di programmazione, spesso abbiamo bisogno di avere una valutazione oggettiva del tempo di esecuzione di più frammenti di codice, per poter valutare quale dei due impiega meno tempo. Infatti il minore tempo di esecuzione di certe parti di codice, specialmente quelle ripetute più volte nel corso del programma o utilizzate in più parti del programma stesso, ha per conseguenza un minore tempo di esecuzione dell’intero programma e quindi migliori prestazioni che vengono percepite positivamente dall’utente.
In questo post vedremo quindi come si crea e come si utilizza una classe in grado di memorizzare il momento iniziale di un test e la differenza tra un momento successivo e il momento iniziale.
La classe è la seguente:
Public Class Cronometro
Private inizio As DateTime
Private durata As TimeSpan
Public Sub New()
inizio = New DateTime
durata = New TimeSpan
End Sub
Public Sub ferma()
durata = CType(DateTime.Now.Subtract(inizio), TimeSpan)
End Sub
Public Sub avvia()
GC.Collect()
GC.WaitForPendingFinalizers()
inizio = DateTime.Now
End Sub
Public ReadOnly Property Result() As TimeSpan
Get
Return durata
End Get
End Property
End Class
Le istruzioni GC.Collect() e GC.WaitForPendingFinalizers() servono per avviare la “raccolta della spazzatura” da parte del Garbage Collector, cioè l’eliminazione degli oggetti non più utilizzati. Infatti, come sappiamo, gli oggetti non vengono eliminati immediatamente al termine del loro utilizzo, ma rimangono in memoria finché il Garbage Collector non decide di eliminarli. In particolare la seconda istruzione (GC.WaitForPendingFinalizers) attende che siano terminati tutti i metodi Finalizer degli oggetti in corso di eliminazione.
Perché avviare esplicitamente il Garbage Collector? E’ presto detto: vogliamo che nel corso del nostro test non avvenga la “raccolta dei rifiuti” che rallenterebbe l’esecuzione e causerebbe l’invalidazione del test stesso.
In un’applicazione Console possiamo poi testare la classe Cronometro con questo codice:
Option Strict On
Imports System.Console
Module Module1
Sub Main()
Dim numeri(99999) As Integer
BuildArray(numeri)
Dim tObj As New Cronometro()
tObj.avvia()
ScriviNumeri(numeri)
tObj.ferma()
Console.WriteLine(“tempo in secondi: “ & _
tObj.Result.TotalSeconds)
Console.Read()
End Sub
Sub BuildArray(ByVal arr() As Integer)
Dim indice As Integer
For indice = 0 To 99999
arr(indice) = indice
Next
End Sub
Sub ScriviNumeri(ByVal arr() As Integer)
Dim indice As Integer
For indice = 0 To arr.GetUpperBound(0)
Console.Write(arr(indice) & ” “)
Next
End Sub
End Module
Quella che abbiamo visto è la soluzione “classica” che viene spesso utilizzata e che, peraltro, va bene con qualsiasi linguaggio OOP (anche quelli non-.NET, fatti gli opportuni adattamenti).
E’ possibile ottenere una soluzione più ordinata e pulita utilizzando la classe System.Diagnostics.Stopwatch, implementata in tutti i Framework .NET dalla versione 2.0 in poi. Per esempio questo è il codice di un’applicazione Console che fa uso di tale classe:
Public Class Test
Shared Sub main()
Dim str As String = “”
Dim watch As New System.Diagnostics.Stopwatch()
watch.Start() ‘ avvio del cronometro
‘ … fai qualcosa …
Dim i As Integer = 0
For i = 1 To 100
str &= “*”
Console.WriteLine(“<” & str & “>”)
Next
watch.Stop() ‘ stop del cronometro
Console.WriteLine(“Tempo impiegato: “ + watch.Elapsed.ToString())
Console.ReadLine()
End Sub
End Class
Attenzione che il test può non funzionare perfettamente in tutti i casi: se il nostro computer è pieno di programmi e servizi in esecuzione, potremmo ottenere dei risultati non corretti. In particolare, quando dobbiamo confrontare i tempi di due versioni di codice diverse (per esempio due algoritmi di ordinamento diversi), lo stato del computer dovrebbe essere il più possibile uguale in entrambe le esecuzioni, altrimenti si rischia di falsare i risultati.
Il consiglio è sempre quello, se possibile, di utilizzare un’installazione “pulita”, con solo i programmi e i servizi indispensabili per l’esecuzione del programma e del relativo test.
Pubblicato su Tips | Contrassegnato da tag: GC, Test, VB.NET | Non ci sono Commenti »