Question

From the IL perspective, what are the main differences (performance wise) between a local Dim variable and a local Static variable?

I've always thought that Dim would allocate storage space every time, whilst Static would allocate storage space only once, hence faster. But as you can see below, this is not the case.

  • A: Dim
  • B: Static

Chart

Public Class Form1

    Public Sub New()
        Me.InitializeComponent()
        Dim b As New Button() With {.Text = "Run", .Height = 30, .Location = New Point(10, 10)}
        AddHandler b.Click, AddressOf Me.Run
        Me.Controls.Add(b)
    End Sub

    Private Sub Run(sender As Object, e As EventArgs)

        Dim count As Integer = 10000
        Dim watch As New Stopwatch()
        Dim list As New Test(Of Control)(count)
        Dim last As Control = list.Items(count - 1)
        Dim a, b As Double, i As Integer

        For i = 1 To 10000
            watch.Restart()
            list.IndexOfA(last)
            a += watch.Elapsed.TotalMilliseconds
        Next

        For i = 1 To 10000
            watch.Restart()
            list.IndexOfB(last)
            b += watch.Elapsed.TotalMilliseconds
        Next

        watch.Stop()
        Array.ForEach(Of Control)(list.Items, Sub(c As Control) c.Dispose())
        list = Nothing

        MessageBox.Show(String.Format("A: {0}{1}B: {2}", a.ToString("F4"), Environment.NewLine, b.ToString("F4")))

    End Sub

    Public Class Test(Of T As {Class, New})

        Public Sub New(count)
            If (count < 0) Then Throw New ArgumentOutOfRangeException("count")
            Dim items As T() = New T(count - 1) {}
            For index As Integer = (count - 1) To 0 Step -1
                items(index) = New T()
            Next
            Me.Items = items
        End Sub

        Public Function IndexOfA(item As T) As Integer
            Dim index As Integer
            Dim length As Integer
            Dim item2 As T
            length = (Me.Items.Length - 1)
            For index = 0 To length
                item2 = Me.Items(index)
                If (item2 Is item) Then
                    Return index
                End If
            Next
            Return -1
        End Function

        Public Function IndexOfB(item As T) As Integer
            Static index As Integer
            Static length As Integer
            Static item2 As T
            length = (Me.Items.Length - 1)
            For index = 0 To length
                item2 = Me.Items(index)
                If (item2 Is item) Then
                    Return index
                End If
            Next
            Return -1
        End Function

        Public ReadOnly Items As T()

    End Class

End Class

Edit

As per comment, I've edited the code so it don't "restart the stopwatch at every loop iteration".

watch.Start()
For i = 1 To 10000
    list.IndexOfA(last)
Next
watch.Stop()
a = watch.Elapsed.TotalMilliseconds

watch.Restart()
For i = 1 To 10000 
    list.IndexOfB(last)
Next
watch.Stop()
b = watch.Elapsed.TotalMilliseconds

The results are almost the same:

  • A: 358,3624
  • B: 538.8570
Était-ce utile?

La solution

The main difference in performance is not how the variables are allocated, it's in how they are accessed.

Local variables are allocated on the stack, which takes no time at all. Literally. The allocation is done by moving the stack pointer, and that is done anyway to create a stack frame for the method, so allocating local variables doesn't take any more time.

Static variables in an instance method are allocated as part of the data for the class, and that is done only once in this case. Allocating another variable only means that more data is allocated, so that doesn't increase the time.

Accessing the variables is a different story. A local variable is accessed by addressing part of the stack frame, which is easy. A static variable on the other hand is accessed by getting a pointer to the static data of the class, and then addressing the variable at an offset from that. That means that every access to a static variable needs a few more instructions.

Autres conseils

VB local static variables are allocated once per instance if they occur within an instance method. They are only allocated once overall if they occur within a Shared method.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top