While code optimization is a controversial topic, curiosity often gets the best of me and I want to know which method of doing something in VB.NET is more efficient.

I’ve developed a very simple, fast method of benchmarking two different functions and determining which method is faster. If you’d like to download the entire code (and skip the article’s text), there is a ZIP file at the end of this page.
As with any benchmarking test, but especially with tests that can execute quickly, you need to select a high-performance timing method that can detect small differences in execution time — enter QueryPerformanceCounter().
QueryPerformanceCounter is an API function that returns by-reference the value of a high-performance counter in “counts” (which can be converted to milliseconds):
Declare Function QueryPerformanceCounter Lib "Kernel32" (ByRef X As Long) As Short
To convert from “counts” to milliseconds, you’ll need to use the QueryPerformanceFrequency API function:
Declare Function QueryPerformanceFrequency Lib "Kernel32" (ByRef X As Long) As Short
By using the QueryPerformanceCounter() function, you can calculate the amount of time elapsed between beginning and ending a function:
Dim Speed1 As Long
Console.WriteLine("Starting benchmark test for function 1...")
QueryPerformanceCounter(lngStart)
Function1()
QueryPerformanceCounter(lngEnd)
Speed1 = lngEnd - lngStart
Finally, you can use this concept by comparing Function1() vs. Function2(). In this example, I’ve compared two different string concatenation method. Again, you can download the source code below.
Module Module1
'Read more at: http://support.microsoft.com/kb/306978
Declare Function QueryPerformanceCounter Lib "Kernel32" (ByRef X As Long) As Short
Declare Function QueryPerformanceFrequency Lib "Kernel32" (ByRef X As Long) As Short
Sub Main()
Dim lngStart As Long, lngEnd As Long
If QueryPerformanceCounter(lngStart) = False Then
Console.WriteLine("High-resolution performance counter not supported - ending.")
Console.ReadKey()
Exit Sub
End If
Dim Speed1 As Long
Console.WriteLine("Starting benchmark test for function 1...")
QueryPerformanceCounter(lngStart)
Function1()
QueryPerformanceCounter(lngEnd)
Speed1 = lngEnd - lngStart
Dim Speed2 As Long
Console.WriteLine("Starting benchmark test for function 2...")
QueryPerformanceCounter(lngStart)
Function2()
QueryPerformanceCounter(lngEnd)
Speed2 = lngEnd - lngStart
Console.WriteLine(vbCrLf & "Speed of function 1: " & ConvertCountsToMSec(Speed1) & " ms")
Console.WriteLine("Speed of function 2: " & ConvertCountsToMSec(Speed2) & " ms")
Console.WriteLine("Absolute difference: " & ConvertCountsToMSec(Math.Abs(Speed2 - Speed1)) & " ms")
If Speed2 > Speed1 Then
Console.WriteLine(vbCrLf & "Function 2 was " & Math.Round(Speed2 / Speed1, 4) & "x faster")
ElseIf Speed1 > Speed2 Then
Console.WriteLine(vbCrLf & "Function 1 was " & Math.Round(Speed1 / Speed2, 4) & "x faster")
Else ' Speed1 = Speed2
Console.WriteLine(vbCrLf & "No difference in speed")
End If
Console.WriteLine(vbCrLf & "Press any key to end ...")
Console.ReadKey()
End Sub
Public Sub Function1()
'Do stuff (method #1)
Dim s As String = "", i As Integer
For i = 0 To 1000
s &= Strings.StrDup(i, "A")
Next
End Sub
Public Sub Function2()
'Do stuff (method #2)
Dim s As New Text.StringBuilder(""), i As Integer
For i = 0 To 1000
s.Append(Strings.StrDup(i, "A"))
Next
End Sub
Public Function ConvertCountsToMSec(ByVal Counts As Long) As Double
Dim Freq As Long
QueryPerformanceFrequency(Freq)
Return Math.Round(Counts / Freq * 1000, 4)
End Function
End Module
Download the entire code: SimpleFunctionBenchmarking.zip [79kb]
Leave a Reply