Home
Foreword
Preface
Class Idioms
Collections
Implements
Constructors
Terminate
Forms
On Error
Frameworks
F.A.Q.
Value-added
FSMs
Constants
GOTO
Hungarian
Nothing
Properties
Big EXEs

Trespasssers will be persecuted

The Visual Basic manuals are generally very good, but they´re not infallible. For example, this often-cited statement from the Programmer´s Guide transcends the usual benign vagueness of technical notes in the VB books by offering demonstrably bad advice:

    "Don't implement a property as a public variable just to avoid the overhead of a function call. Behind the scenes, Visual Basic will implement the public variables in your class modules as pairs of property procedures anyway, because this is required by the type library."

Whatever the underlying COM mechanisms are, the clear implication is that using a naked Public variable instead of Property Let and Property Get functions will offer no performance benefit. The reality is somewhat different: a Property Get takes four times as long as a naked variable.

I discovered this when I was tinkering with a new mechanism for handling errors and I needed to find the fastest way to check a flag variable. Since unattached global variables are generally a bad idea I was keen to keep my flag as a class property, and I wrote a program to check the timing implications of various options. I was surprised to find that the accepted wisdom is wrong.

There isn´t much to say about this except to demonstrate it, so here´s my program and the output from a sample run:


vartiming

And the output:


1.07s

0.24s

0.24s

1.78s

 

0.40s

And here´s the code. Have fun!


Example Code:
Property Let v. Naked Variable

Form Form1 (Startup)

Option Explicit

Private Sub cmdBASProp_Click()

    GTimer.StartTimer
    Dim n As Long
    For n = 1 To CLng(txtTimes.Text)
        If GBASFlags.Flag Then Exit Sub
    Next n
    MsgBox Format$(GTimer.StopTimer / 1000, "##0.00")

End Sub

Private Sub cmdBASQualVar_Click()

    GTimer.StartTimer
    Dim n As Long
    For n = 1 To CLng(txtTimes.Text)
        If GBASFlags.Flag2 Then Exit Sub
    Next n
    MsgBox Format$(GTimer.StopTimer / 1000, "##0.00")

End Sub

Private Sub cmdBASVar_Click()

    GTimer.StartTimer
    Dim n As Long
    For n = 1 To CLng(txtTimes.Text)
        If Flag2 Then Exit Sub
    Next n
    MsgBox Format$(GTimer.StopTimer / 1000, "##0.00")

End Sub

Private Sub cmdCLSQualVar_Click()

    Dim obj As CCLSFlags
    Set obj = New CCLSFlags
   
    GTimer.StartTimer
    Dim n As Long
    For n = 1 To CLng(txtTimes.Text)
        If obj.Flag2 Then Exit Sub
    Next n
    MsgBox Format$(GTimer.StopTimer / 1000, "##0.00")

End Sub

Private Sub cmdCLSProp_Click()

    Dim obj As CCLSFlags
    Set obj = New CCLSFlags
   
    GTimer.StartTimer
    Dim n As Long
    For n = 1 To CLng(txtTimes.Text)
        If obj.Flag Then Exit Sub
    Next n
    MsgBox Format$(GTimer.StopTimer / 1000, "##0.00")

End Sub
 

Class CCLSFlags

Option Explicit

Public Flag2 As Boolean
Private m_bFlag As Boolean

Public Property Get Flag() As Boolean
    Flag = m_bFlag
End Property
 

BAS GBASFlags

Option Explicit

Public Flag2 As Boolean
Private m_bFlag As Boolean

Public Property Get Flag() As Boolean
    Flag = m_bFlag
End Property
 

BAS GTimer

Option Explicit

Public Declare Function GetTickCount Lib "kernel32" () As Long

Private m_lStart As Long

Public Sub StartTimer()
    m_lStart = GetTickCount
End Sub

Public Function StopTimer() As Long
    StopTimer = GetTickCount - m_lStart
End Function

Key Spinner

© 1998 - 2009 Mark Hurst. All rights reserved.   Updated March 01, 2009