mario.deghetto

Visual Basic & .NET
posts - 332, comments - 79, trackbacks - 0

#36: Calcolare il tempo di esecuzione di un frammento di codice (VB.NET)

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.

Print | posted on venerdì 15 gennaio 2010 5.42 |

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 1 and 5 and type the answer here:

Powered by: