Reputation: 65
I'm trying to optimize an assembly which manipulate large data, but there is something I don't understand : why in the following code, looking for the minimum is two times longer if called from a class.
Sub Main()
Dim t As New Stopwatch()
Dim ar(100000) As Double
For i = 0 To ar.Length - 1
ar(i) = i
Next
t.Start()
Dim Min As Double
Dim idx As Integer
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To ar.Length - 1
If ar(i) < Min Then
idx = i
Min = ar(i)
End If
Next
Next
t.Stop()
Console.WriteLine("Min in Main sub : " & t.ElapsedMilliseconds & "ms")
Dim test As New SomeArray
test.ar = ar
t.Reset() : t.Start()
test.Minimum()
t.Stop()
Console.WriteLine("Min in class : " & t.ElapsedMilliseconds & "ms")
End Sub
Public Class SomeArray
Public Property ar As Double()
Public Function Minimum() As Double
Dim Min As Double
Dim idx As Integer
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To ar.Length - 1
If ar(i) < Min Then
idx = i
Min = ar(i)
End If
Next
Next
Return Min
End Function
End Class
Example of result:
Min in Main sub: 458 ms
Min in class : 815 ms
SomeArray.Minimum is exactly a copy/past of the Main, so why it's so longer?
Tested with Framework 3.5.
UPDATE
First answers suggest that using fields instead of properties is faster. I confirm that until I'm in DEBUG mode. But as suggested by @SreeHarshaNellore result in RELEASE mode is a bit different. To perform some test I've used following class :
Public Class SomeArray 'Original one
Public Property ar As Double()
Public Function RecalcMinimum() As Double
Dim Min As Double
Dim idx As Integer
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To ar.Length - 1
If ar(i) < Min Then
idx = i
Min = ar(i)
End If
Next
Next
Return Min
End Function
End Class
Public Class SomeArray2 'with private field
Private _ar As Double()
Public Sub New(ar As Double())
_ar = ar
End Sub
Public Function RecalcMinimum() As Double
Dim Min As Double
Dim idx As Integer
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To _ar.Length - 1
If _ar(i) < Min Then
idx = i
Min = _ar(i)
End If
Next
Next
Return Min
End Function
End Class
Public Class SomeArray3 'Same as SomeArray2 but with local array in loop
Private _ar As Double()
Public Sub New(ar As Double())
_ar = ar
End Sub
Public Function RecalcMinimum() As Double
Dim Min As Double
Dim idx As Integer
Dim l As Double() = _ar
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To l.Length - 1
If l(i) < Min Then
idx = i
Min = l(i)
End If
Next
Next
Return Min
End Function
End Class
Public Class SomeArray4 'With property but access with private field
Public Property ar As Double()
Public Function RecalcMinimum() As Double
Dim Min As Double
Dim idx As Integer
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To _ar.Length - 1
If _ar(i) < Min Then
idx = i
Min = _ar(i)
End If
Next
Next
Return Min
End Function
End Class
Public Class SomeArray5 'Array as function argument
Public Function RecalcMinimum(ar As Double()) As Double
Dim Min As Double
Dim idx As Integer
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To ar.Length - 1
If ar(i) < Min Then
idx = i
Min = ar(i)
End If
Next
Next
Return Min
End Function
End Class
And the result is a bit surprising in RELEASE mode:
Main sub : 135 ms
SomeArray : 143 ms '(property and property access)
SomeArray2 : 272 ms '(private field)
SomeArray3 : 143 ms '(private field + local array)
SomeArray4 : 261 ms '(property but field access)
SomeArray5 : 144 ms '(array as function argument)
As suggested by @SreeHarshaNellore, in RELEASE mode SomeArray is as fast as Main. Accessing to private filed is now slower (completely differente from DEBUG mode). Moreover, if I add a local variable that points to the private field ("l" in SomeArray3) I back to the Mais speed.
Any explanation ?
For information in DEBUG I get:
Main sub : 402 ms
SomeArray : 708 ms '(property and property access)
SomeArray2 : 415 ms '(private field)
SomeArray3 : 371 ms '(private field + local array)
SomeArray4 : 435 ms '(property but field access)
SomeArray5 : 409 ms '(array as function argument)
(SomArray 3 is again the fastest)
Upvotes: 1
Views: 137
Reputation: 438
I got the same results as @Alex when I compiled for DEBUG config.
Then, I tested the code with both backing field and automatic BUT in RELEASE config using
.NET 4.6.1
There is no difference between these 2 approaches
It takes approximately
100ms for Main method
110ms for Class method
Which means that the code is greatly optimised in RELEASE mode.
Upvotes: 1
Reputation: 56755
If you change the SomeArray class to use the backing field instead of the Property, the difference goes away (this is what I always do in my own code):
Public Class SomeArray
Public Property ar As Double()
Public Function Minimum() As Double
Dim Min As Double
Dim idx As Integer
For j = 1 To 1000
Min = Double.MaxValue
idx = -1
For i = 0 To ar.Length - 1
If _ar(i) < Min Then
idx = i
Min = _ar(i)
End If
Next
Next
Return Min
End Function
End Class
So clearly, the difference is the property accessor overhead.
Upvotes: 0