Struct constructors bad?

snarfblam

Mega-Ultra Chicken
Joined
Jun 10, 2003
Messages
1,832
Location
USA
User Rank
*Expert*
Another chapter in my never ending quest to micro-optimize. Anyone up for a long read?

I was thinking about structs. I make a lot of use of them, because I hate to create garbage collected objects when they arent neccessary. I prefer to let the memory be reclaimed when they go out of scope and save the memory used to manage the object. (Of course, I use classes when they are appropriate, too.)

But I was wondering about using struct constructors. When you use the StructInstance = New Struct syntax, I would image that a new struct is allocated on the stack, initialized to default values, the constructor is called, then the newly allocated struct is assigned to the original. If you were to create a static intialization method, however, you could avoid the creation and intialization of a new struct on the stack.

I reasoned, however, that the inefficiencies of using a constructor to assign a value to a struct would be optimized out. Of course, I had to see for myself. I coded a constructor, and disassembled it, and discovered that indeed, a new struct is allocatated, initialized to default values, the constructor is called (we are essentially initializing twice, here), and then is assigned back to the original struct. I did this with a release build because this is the build that the end-user will be using.

I created a test struct with a constructor and a static method both of which could be used to initialize an already allocated struct.

[VB]
Public Structure TestStruct
Members 1 through 5
Dim M1, M2, M3, M4, M5 As Single

Using constructor to initialize
Public Sub New(ByVal A As Single, ByVal B As Single, _
ByVal C As Single, ByVal D As Single, ByVal E As Single)
M1 = A
M2 = B
M3 = C
M4 = D
M5 = E
End Sub

Using shared method to initialize
Shared Sub StaticInit(ByRef Struct As TestStruct, ByVal A As Single, _
ByVal B As Single, ByVal C As Single, ByVal D As Single, ByVal E As Single)
Struct.M1 = A
Struct.M2 = B
Struct.M3 = C
Struct.M4 = D
Struct.M5 = E
End Sub
End Structure
[/VB]

And of course we have a function to test these two methods:
[VB]
Sub Test()
Struct to be initialized
Dim Struct As TestStruct
Times to init struct
Dim Times As Integer = 10000000

Test static function
Dim Start As Integer = System.Environment.TickCount
For i As Integer = 0 To Times
TestStruct.StaticInit(Struct, 1, 2, 3, 4, 5)
Next
Dim FirstTime As Integer = System.Environment.TickCount - Start

Test constructor
Start = System.Environment.TickCount
For i As Integer = 0 To Times
Struct = New TestStruct(1, 2, 3, 4, 5)
Next
Dim SecondTime As Integer = System.Environment.TickCount - Start

Display results
MessageBox.Show(FirstTime.ToString & " " & SecondTime.ToString)
End Sub
[/VB]
Well, I was dissapointed to see that the constructor, the easier and more intuitive method, ran considerably slower than the static intialization function. The results for six runs were as follows (timed in milliseconds, .ctor = constructor):
Code:
Run  .ctor Static | Run  .ctor Static
1    551   160    | 4    521   190
2    531   160    | 5    521   190
3    541   160    | 6    521   190
In the last three runs, I reversed the order of the loops, testing the constructor first and then the static method.

This also begs the question as to whether one method or the other is faster when initializing a struct when it is allocated, i.e. Dim X As New Struct() vs. Dim X As Struct : Struct.Init(X).

Using a similar test, these are the results that I got, again, switching the order of the tests on the second set of runs:
Code:
Run  .ctor Static | Run  .ctor Static
1    360   170    | 4    441   170
2    351   160    | 5    351   170
3    350   170    | 6    361   170
It looked a little better for the constructor in the second test, but still disappointing. Of course, youre wondering when you will need to initialize ten million structs, and of course the answer is never. But maybe knowing that constructors arent particularly efficient can help you sort out a bottle-neck issue someday, or give your Direct3D game a speed boost when you create hundreds or thousands of vertices.
 
Back
Top