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 aren't 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.
And of course we have a function to test these two methods:
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):
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:
It looked a little better for the constructor in the second test, but still disappointing. Of course, you're wondering when you will need to initialize ten million structs, and of course the answer is never. But maybe knowing that constructors aren't 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.
I was thinking about structs. I make a lot of use of them, because I hate to create garbage collected objects when they aren't 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.
Visual Basic:
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
And of course we have a function to test these two methods:
Visual Basic:
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
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
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