为什么调用类函数要慢得多

时间:2018-07-17 17:33:18

标签: .net vb.net performance

我正在尝试优化处理大数据的程序集,但是我不明白:为什么在下面的代码中,如果从类中调用,寻找最小值的时间要长两倍。

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

结果示例:

Min in Main sub: 458 ms
Min in class   : 815 ms

SomeArray.Minimum恰好是Main的副本/过去,那么为什么它那么长?

经过Framework 3.5测试。

更新

第一个答案表明,使用字段代替属性更快。我确认,直到进入调试模式。但是正如@SreeHarshaNellore所建议的那样,RELEASE模式下的结果有些不同。 为了进行测试,我使用了以下课程:

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

在RELEASE模式下,结果令人惊讶:

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)

如@SreeHarshaNellore所建议,在RELEASE模式下,SomeArray与Main一样快。现在访问私有文件的速度较慢(与DEBUG模式完全不同)。 此外,如果我添加一个指向私有字段(在SomeArray3中为“ l”)的局部变量,则会回到Mais速度。

任何解释吗?

有关调试的信息,我得到:

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再次是最快的)

2 个答案:

答案 0 :(得分:1)

public class SampleAppDbContext
{
    //..
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //Increase your Setting Value to 4000 chars
        modelBuilder.Entity<Abp.Configuration.Setting>().Property(u => u.Value).HasMaxLength(4000);
        //..
    }
}

这意味着代码在RELEASE模式下得到了极大的优化。

答案 1 :(得分:0)

如果您将SomeArray类更改为使用后备字段而不是Property,则区别消失了(这是我始终在自己的代码中所做的事情):

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

很明显,区别在于属性访问器的开销。