Performance techniques for converting Object to structures
If you're
converting Object expressions to
structures, you can tweak your code for a drastic performance improvement.
Because unboxing a Nothing
reference throws an exception, a conversion from Object to a structure involves testing for a Nothing reference before performing the unbox. For
example:
Structure
Foo
Public a As Integer
Public b As Integer
End
Structure
Module
Test
Sub Foo(ByVal o As Object)
Dim x As Foo
x = o
End Sub
End
Module
The
compiler actually generates this code behind the scenes:
Module
Test
Sub Foo(ByVal o As Object)
Dim x As Foo
Dim _t As Object = o
If _t Is Nothing
Then
_t = System.Activator.CreateInstance(GetType(Foo))
End If
x = DirectCast(_t, Foo)
End Sub
End
Module
In the
case that o is Nothing, x gets a zeroed-out, or default, instance of Foo. Getting this default instance of Foo is costly
because the compiler uses System.Activator.CreateInstance to create one.
You can
avoid the call to System.Activator.CreateInstance
by performing the Nothing check by
hand and supplying a ready-made default instance of your structure. There are two techniques I can think of to
supply a ready-made default, either by using a local variable or, slightly
safer, a Shared ReadOnly
field declared on the structure itself.
Option 1:
Module
Test
Sub Foo(ByVal o As Object)
Dim x As Foo
Dim DEFAULT As
Foo 'Don't ever modify this
If o Is Nothing Then
x = DEFAULT
Else
x = DirectCast(o, Foo)
End If
End Sub
End
Module
Option 2:
Structure
Foo
Public a As Integer
Public b As Integer
Public Shared ReadOnly
DEFAULT As Foo
End
Structure
Module
Test
Sub Foo(ByVal o As Object)
Dim x As Foo
If o Is Nothing Then
x = Foo.DEFAULT
Else
x = DirectCast(o, Foo)
End If
End Sub
End
Module
The nice
thing about Option 1 is that you can use this technique for any structure. However, Option 2 is the better choice
because, assuming you can modify the declaration of the structure, the compiler
will stop you from accidentally modifying the DEFAULT variable, thereby
preserving its clean state.
Note that
assigning Nothing
to a structure generates a call to CreateInstance as well.
You should use these techniques rather than assigning Nothing to a structure:
Module
Test
Sub Foo(ByVal o As Object)
Dim x As Foo
x = Nothing 'Okay
x = Foo.DEFAULT 'Better
End Sub
End
Module
Also note
that these techniques pertain to Structures,
not intrinsic value types such as Byte,
Integer, Long, Double, etc. Casting from Object to Integer will not involve a call to CreateInstance.
We're
definitely looking at having the compiler use these same techniques (probably
Option 1 where the local will be an inaccessible temporary variable) in the
next version.
Comments
- Anonymous
July 22, 2003
The comment has been removed - Anonymous
July 23, 2003
thanks! I've updated it.