В чем разница между dim на уровне элемента и static на уровне процедуры? - PullRequest
5 голосов
/ 06 января 2010

В Visual Basic 2008 есть два разных способа достижения одной и той же цели:

Dim на уровне участника:

Dim counter1 as integer = 0
Dim counter2 as integer = 180
Public Sub SampleSub1()
   Counter1 += 1 : If (Counter1 > 14) Then Counter1 = 0
   Counter2 += 1 : If (Counter2 > 240) Then Counter2 = 0
End Sub

Тогда на уровне процедуры есть статика:

Public Sub SampleSub2()
   Static Dim counter1 as integer = 0
   Static Dim counter2 as integer = 180
   Counter1 += 1 : If (Counter1 > 14) Then Counter1 = 0
   Counter2 += 1 : If (Counter2 > 240) Then Counter2 = 0
End Sub

Я выполняю цикл примерно 8 миллионов раз за 7 секунд (с обработкой большего количества данных), и использование статического метода на счетчиках на самом деле занимает около 500 мс. Статический метод обеспечивает лучшее управление памятью? Почему это медленнее?

Кроме того, я объявляю свои объекты, которые повторно используются с dim на уровне элемента или, по крайней мере, снаружи для циклов, например:

Dim SampleObject as SampleClass
Public Sub SampleSub3()
   SampleObject = TheQueue.Dequeue()
End Sub

Должен ли я использовать метод Static (который кажется медленнее) в подобных ситуациях или метод dim на уровне элемента, который я уже использую?

Я воспроизвел проблему с этим кодом в тестовом приложении:

Public Class Form1
Dim EndLoop As Integer = 50000000
Dim stopwatch1 As New Stopwatch

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    stopwatch1.Reset()
    stopwatch1.Start()

    For cnt As Integer = 1 To EndLoop
        test1()
    Next
    stopwatch1.Stop()

    Label1.Text = "Loop1: " & stopwatch1.ElapsedMilliseconds

    stopwatch1.Reset()
    stopwatch1.Start()
    For cnt As Integer = 1 To EndLoop
        test2()
    Next
    stopwatch1.Stop()

    Label2.Text = "Loop2: " & stopwatch1.ElapsedMilliseconds
End Sub
End Class

Public Module TestModule
Dim counter1 As Integer = 0
Dim counter2 As Integer = 180
Public Sub test1()
    counter1 += 1 : If (counter1 > 14) Then counter1 = 0
    counter2 += 1 : If (counter2 > 240) Then counter2 = 0
    COW1(counter1, counter2)
End Sub

Public Sub test2()
    Static counter3 As Integer = 0
    Static counter4 As Integer = 180
    counter3 += 1 : If (counter3 > 14) Then counter3 = 0
    counter4 += 1 : If (counter4 > 240) Then counter4 = 0
    COW1(counter3, counter4)
End Sub


Public Sub COW1(ByVal counter1 As Integer, ByVal counter2 As Integer)

End Sub
End Module

Замедление с использованием статических переменных не произойдет, если я не вызываю подпрограмму из другого модуля, как в примере выше.

1 Ответ

5 голосов
/ 06 января 2010

Статические локальные переменные - странная особенность VB.Net. Когда вы их компилируете, они просто представляются статической переменной уровня класса за кулисами.

Однако, если вы инициализируете и объявляете статическую локальную переменную одновременно, на самом деле происходит то, что компилятор прикрепляет вокруг себя класс Monitor, чтобы гарантировать, что он не может быть инициализирован несколькими потоками одновременно .

Вероятно, вы видите накладные расходы этого монитора. Попробуйте удалить инициализацию из декларативного оператора и посмотрите, заметили ли вы улучшение производительности.

...