Вот результаты моего собственного тестирования скорости (наконец).
В своих тестах я использовал следующий код. Я использовал 1 миллион итераций, чтобы сократить время ожидания. От -1 до 13 - дать работу за границей. Когда требуется настройка массива, он включается в общее время, но выполняется только один раз. Каждая функция получила свою собственную процедуру вызова с жестко закодированным именем (X):
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabel_X(j, False, False)
str = ComputeLabel_X(j, True, False)
str = ComputeLabel_X(j, False, True)
Next
Next
Я также получил разные результаты при запуске кода с помощью F5 (разбить код при ошибке) и Ctrl-F5 (запустить вне отладчика). Я полагаю, что второй имеет больше смысла для среды кода SSRS, поскольку ничто не будет подключаться к процессу для его отладки.
Все результаты компилируются без отладки (Ctrl-F5).
- Расс: 613 мс (добавлена проверка границ)
- Эрик: 614 мс (то же самое, что и Russ, но массивы заполнены литералом массива {} вместо отдельных операторов)
- Erik2: 526 мс (от 0 до 12, с дополнительными от 0 до 2, без проверки границ)
- Стив: 660 мс
- Стив2: 873 мс (удалить ElseIf для отдельных операторов If)
- Новое: 2977 мс (первая идея из моего предыдущего ответа)
- Исходное сообщение: 3915 мс * - исправлено (было в 10 раз меньше)
- Оригинал: 3947 мс (версия, которую вы никогда не видели, та, которую я оптимизировал для публикации здесь)
- Выберите: 11068 мс
- BigArray: 12565 мс (вычисление индекса в большой массив с математикой)
Несмотря на то, что время выполнения может колебаться на целых 100 мс для более высоких значений, рейтинги, как правило, остаются неизменными, за исключением версий Russ и Erik, которые менялись местами.
Takeaways:
Создание массива один раз незначительно. Выполнение этого в виде отдельных операторов или литерала массива {} идентично.
Проверка границ метода массива на 20% дороже.
Интуитивное расширение всего, кажется, должно быть быстрее, но это не так. Я не знаю почему. Возможно, это связано с размером строки кэша процессора и компромиссами предварительной загрузки, или с чем-то вроде этого.
Единственными реальными изменениями, которые я внес из исходной функции в функцию, которую я разместил в своем вопросе, были: 1) Возврат из каждого оператора case вместо присвоения строки переменной и возврата ее в конце (плюс удаление переменная), 2) поменяйте местами независимый порядок операторов If Flag и измените второй If на ElseIf. Улучшение на 1% было незначительным
Похоже, я должен быть в состоянии что-то обобщить из того факта, что моя версия, указанная как "Новая" (первый запрос в другом ответе, который я разместил), сделала это плохо. Это более длинные строки? Неужели возврат одинаково быстр независимо от того, где в процедуре он выполняется, но выпадение из оператора Case для выполнения большего количества инструкций происходит медленно?
Русская версия массива самая быстрая. Поиск в массиве выполняется быстрее, чем оператор case с конкатенацией строк.
На данный момент я не уверен, как объяснить, почему Новая версия работает быстрее.
Функция выбора супер, супер медленная.
Из-за этих тестов я должен присудить ответ на этот вопрос nobugz, который заявил, что я не могу оптимизировать данный код. Пока он был прав!
Обновление: я действительно сожалею об ошибке, которую я сделал, которая обнуляла ноль на количестве итераций, проверяющих версию Initial Post. Все было исправлено.
Приложение: (исправленный) код тестирования:
Module Module1
Dim _Labels(12) As String
Dim _ConditionalLabels(12) As String
Dim _HeldLabels(12) As String
Dim Labels() As String
Dim ConditionalLabels() As String
Dim HeldLabels() As String
Dim OrderLabelsBigArray(38) As String
Sub Main()
Dim sw As New Stopwatch()
sw.Start()
ComputeLabelsFirstPosted()
sw.Stop()
Console.WriteLine("FirstPosted " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsRuss()
sw.Stop()
Console.WriteLine("Russ " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsErik()
sw.Stop()
Console.WriteLine("Erik " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsErik2()
sw.Stop()
Console.WriteLine("Erik2 " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsBigArray()
sw.Stop()
Console.WriteLine("BigArray " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsSteve()
sw.Stop()
Console.WriteLine("Steve " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsSteve2()
sw.Stop()
Console.WriteLine("Steve2 " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsNew()
sw.Stop()
Console.WriteLine("New " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsChoose()
sw.Stop()
Console.WriteLine("Choose " & sw.ElapsedMilliseconds & " ms")
sw.Reset()
sw.Start()
ComputeLabelsOriginal()
sw.Stop()
Console.WriteLine("Original " & sw.ElapsedMilliseconds & " ms")
Console.Read()
End Sub
Public Sub ComputeLabelsFirstPosted()
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelFirstPosted(j, False, False)
str = ComputeLabelFirstPosted(j, True, False)
str = ComputeLabelFirstPosted(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelFirstPosted(ByVal Action As Integer, ByVal IsHeld As Boolean, ByVal IsConditional As Boolean) As String
Dim Prefix As String = ""
If IsConditional Then
Prefix = "Conditional "
ElseIf IsHeld Then
Prefix = "Held "
End If
Select Case Action
Case 0
Return ""
Case 1
Return Prefix & "Cancelled"
Case 2
Return Prefix & "Discontinued"
Case 3
Return Prefix & "Suspended"
Case 4
Return Prefix & "Unsuspended"
Case 6
Return Prefix & "Collected"
Case 7
Return Prefix & "Released from Hold"
Case 8
Return Prefix & "Modified"
Case 9
Return Prefix & "Discontinued for the Future"
Case 10
Return Prefix & "Verified"
Case 11
Return Prefix & "Modified And Verified"
Case 12
Return "Hold " & Prefix & "Cancelled"
Case Else
Return ""
End Select
End Function
Sub ComputeLabelsRuss()
_Labels(0) = ""
_Labels(1) = "Cancelled"
_Labels(2) = "Discontinued"
_Labels(3) = "Suspended"
_Labels(4) = "Unsuspended"
_Labels(6) = "Collected"
_Labels(7) = "Released from Hold"
_Labels(8) = "Modified"
_Labels(9) = "Discontinued for the Future"
_Labels(10) = "Verified"
_Labels(11) = "Modified And Verified"
_Labels(12) = "Hold Cancelled"
_ConditionalLabels(0) = ""
_ConditionalLabels(1) = "Conditional Cancelled"
_ConditionalLabels(2) = "Conditional Discontinued"
_ConditionalLabels(3) = "Conditional Suspended"
_ConditionalLabels(4) = "Conditional Unsuspended"
_ConditionalLabels(6) = "Conditional Collected"
_ConditionalLabels(7) = "Conditional Released from Hold"
_ConditionalLabels(8) = "Conditional Modified"
_ConditionalLabels(9) = "Conditional Discontinued for the Future"
_ConditionalLabels(10) = "Conditional Verified"
_ConditionalLabels(11) = "Conditional Modified And Verified"
_ConditionalLabels(12) = "Hold Conditional Cancelled"
_HeldLabels(0) = ""
_HeldLabels(1) = "Held Cancelled"
_HeldLabels(2) = "Held Discontinued"
_HeldLabels(3) = "Held Suspended"
_HeldLabels(4) = "Held Unsuspended"
_HeldLabels(6) = "Held Collected"
_HeldLabels(7) = "Held Released from Hold"
_HeldLabels(8) = "Held Modified"
_HeldLabels(9) = "Held Discontinued for the Future"
_HeldLabels(10) = "Held Verified"
_HeldLabels(11) = "Held Modified And Verified"
_HeldLabels(12) = "Hold Held Cancelled"
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelRuss(j, False, False)
str = ComputeLabelRuss(j, True, False)
str = ComputeLabelRuss(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelRuss(ByVal Action As Integer, ByVal Held As Boolean, ByVal Conditional As Boolean) As String
If Action < 0 OrElse Action > 12 Then Return ""
If Conditional Then Return _ConditionalLabels(Action)
If Held Then Return _HeldLabels(Action)
Return _Labels(Action)
End Function
Public Sub ComputeLabelsNew()
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelNew(j, False, False)
str = ComputeLabelNew(j, True, False)
str = ComputeLabelNew(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelNew(ByVal Action As Integer, ByVal IsHeld As Boolean, ByVal IsConditional As Boolean) As String
Dim Status As String = ""
Select Case Action
Case 0
Return ""
Case 1
Status = "Cancelled"
Case 2
Status = "Discontinued"
Case 3
Status = "Suspended"
Case 4
Status = "Unsuspended"
Case 6
Status = "Collected"
Case 7
Status = "Released from Hold"
Case 8
Status = "Modified"
Case 9
Status = "Discontinued for the Future"
Case 10
Status = "Verified"
Case 11
Status = "Modified And Verified"
Case 12
If IsConditional Then Return "Hold Conditional Cancelled"
If IsHeld Then Return "Hold Held Cancelled"
Return "Hold Cancelled"
Case Else
Return ""
End Select
If IsConditional Then Return "Conditional " & Status
If IsHeld Then Return "Held " & Status
Return Status
End Function
Sub ComputeLabelsErik()
Labels = New String() {"", "Cancelled", "Discontinued", "Suspended", "Unsuspended", "", "Collected", "Released from Hold", "Modified", "Discontinued for the Future", "Verified", "Modified And Verified", "Hold Cancelled"}
ConditionalLabels = New String() {"", "Conditional Cancelled", "Conditional Discontinued", "Conditional Suspended", "Conditional Unsuspended", "Conditional ", "Conditional Collected", "Conditional Released from Hold", "Conditional Modified", "Conditional Discontinued for the Future", "Conditional Verified", "Conditional Modified And Verified", "Hold Cancelled"}
HeldLabels = New String() {"", "Held Cancelled", "Held Discontinued", "Held Suspended", "Held Unsuspended", "Held ", "Held Collected", "Held Released from Hold", "Held Modified", "Held Discontinued for the Future", "Held Verified", "Held Modified And Verified", "Hold Cancelled"}
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelErik(j, False, False)
str = ComputeLabelErik(j, True, False)
str = ComputeLabelErik(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelErik(ByVal Action As Integer, ByVal Held As Boolean, ByVal Conditional As Boolean) As String
If Action < 0 OrElse Action > 12 Then Return ""
If Conditional Then Return ConditionalLabels(Action)
If Held Then Return HeldLabels(Action)
Return Labels(Action)
End Function
Sub ComputeLabelsErik2()
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = 0 To 12
str = ComputeLabelErik2(j, False, False)
str = ComputeLabelErik2(j, True, False)
str = ComputeLabelErik2(j, False, True)
Next
For j As Integer = 1 To 2
str = ComputeLabelErik2(j, False, False)
str = ComputeLabelErik2(j, True, False)
str = ComputeLabelErik2(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelErik2(ByVal Action As Integer, ByVal Held As Boolean, ByVal Conditional As Boolean) As String
If Conditional Then Return ConditionalLabels(Action)
If Held Then Return HeldLabels(Action)
Return Labels(Action)
End Function
Public Sub ComputeLabelsOriginal()
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelOriginal(j, False, False)
str = ComputeLabelOriginal(j, True, False)
str = ComputeLabelOriginal(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelOriginal(ByVal Action As Integer, ByVal bIsHeld As Boolean, _
ByVal bIsConditional As Boolean) As String
Dim strReprintLabel As String = ""
Dim strOrderActionPrefix As String = ""
If (bIsHeld) Then
strOrderActionPrefix = "Held "
End If
If (bIsConditional) Then
strOrderActionPrefix = "Conditional "
End If
Select Case Action
Case 0 ' Normal Order
strReprintLabel = ""
Case 1
strReprintLabel = strOrderActionPrefix & "Order Cancelled"
Case 2
strReprintLabel = strOrderActionPrefix & "Order Discontinued"
Case 3
strReprintLabel = strOrderActionPrefix & "Order Suspended"
Case 4
strReprintLabel = strOrderActionPrefix & "Order Unsuspended"
Case 6
strReprintLabel = strOrderActionPrefix & "Order Collected"
Case 7
strReprintLabel = strOrderActionPrefix & "Order Released from Hold"
Case 8
strReprintLabel = strOrderActionPrefix & "Order Modified"
Case 9
strReprintLabel = strOrderActionPrefix & "Order Discontinued for the Future"
Case 10
strReprintLabel = strOrderActionPrefix & "Order Verified"
Case 11
strReprintLabel = strOrderActionPrefix & "Order Modified And Verified"
Case 12
strReprintLabel = "Hold " & strOrderActionPrefix & "Order Cancelled"
Case Else
strReprintLabel = ""
End Select
Return strReprintLabel
End Function
Sub ComputeLabelsSteve2()
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelSteve2(j, False, False)
str = ComputeLabelSteve2(j, True, False)
str = ComputeLabelSteve2(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelSteve2(ByVal Action As Integer, ByVal IsHeld As Boolean, ByVal IsConditional As Boolean) As String
Select Case Action
Case 0
Return ""
Case 1
If IsConditional Then Return "Conditional Cancelled"
If IsHeld Then Return "Held Cancelled"
Return "Cancelled"
Case 2
If IsConditional Then Return "Conditional Discontinued"
If IsHeld Then Return "Held Discontinued"
Return "Discontinued"
Case 3
If IsConditional Then Return "Conditional Suspended"
If IsHeld Then Return "Held Suspended"
Return "Suspended"
Case 4
If IsConditional Then Return "Conditional Unsuspended"
If IsHeld Then Return "Held Unsuspended"
Return "Unsuspended"
Case 6
If IsConditional Then Return "Conditional Collected"
If IsHeld Then Return "Held Collected"
Return "Collected"
Case 7
If IsConditional Then Return "Conditional Released from Hold"
If IsHeld Then Return "Held Released from Hold"
Return "Released from Hold"
Case 8
If IsConditional Then Return "Conditional Modified"
If IsHeld Then Return "Held Modified"
Return "Modified"
Case 9
If IsConditional Then Return "Conditional Discontinued for the Future"
If IsHeld Then Return "Held Discontinued for the Future"
Return "Discontinued for the Future"
Case 10
If IsConditional Then Return "Conditional Verified"
If IsHeld Then Return "Held Verified"
Return "Verified"
Case 11
If IsConditional Then Return "Conditional Modified And Verified"
If IsHeld Then Return "Held Modified And Verified"
Return "Modified And Verified"
Case 12
If IsConditional Then Return "Hold Conditional Cancelled"
If IsHeld Then Return "Hold Held Cancelled"
Return "Hold Cancelled"
Case Else
Return ""
End Select
End Function
Sub ComputeLabelsSteve()
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelSteve(j, False, False)
str = ComputeLabelSteve(j, True, False)
str = ComputeLabelSteve(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelSteve(ByVal Action As Integer, ByVal IsHeld As Boolean, ByVal IsConditional As Boolean) As String
Select Case Action
Case 0
Return ""
Case 1
If IsConditional Then
Return "Conditional Cancelled"
ElseIf IsHeld Then
Return "Held Cancelled"
Else
Return "Cancelled"
End If
Case 2
If IsConditional Then
Return "Conditional Discontinued"
ElseIf IsHeld Then
Return "Held Discontinued"
Else
Return "Discontinued"
End If
Case 3
If IsConditional Then
Return "Conditional Suspended"
ElseIf IsHeld Then
Return "Held Suspended"
Else
Return "Suspended"
End If
Case 4
If IsConditional Then
Return "Conditional Unsuspended"
ElseIf IsHeld Then
Return "Held Unsuspended"
Else
Return "Unsuspended"
End If
Case 6
If IsConditional Then
Return "Conditional Collected"
ElseIf IsHeld Then
Return "Held Collected"
Else
Return "Collected"
End If
Case 7
If IsConditional Then
Return "Conditional Released from Hold"
ElseIf IsHeld Then
Return "Held Released from Hold"
Else
Return "Released from Hold"
End If
Case 8
If IsConditional Then
Return "Conditional Modified"
ElseIf IsHeld Then
Return "Held Modified"
Else
Return "Modified"
End If
Case 9
If IsConditional Then
Return "Conditional Discontinued for the Future"
ElseIf IsHeld Then
Return "Held Discontinued for the Future"
Else
Return "Discontinued for the Future"
End If
Case 10
If IsConditional Then
Return "Conditional Verified"
ElseIf IsHeld Then
Return "Held Verified"
Else
Return "Verified"
End If
Case 11
If IsConditional Then
Return "Conditional Modified And Verified"
ElseIf IsHeld Then
Return "Held Modified And Verified"
Else
Return "Modified And Verified"
End If
Case 12
If IsConditional Then
Return "Hold Conditional Cancelled"
ElseIf IsHeld Then
Return "Hold Held Cancelled"
Else
Return "Hold Cancelled"
End If
Case Else
Return ""
End Select
End Function
Sub ComputeLabelsChoose()
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelChoose(j, False, False)
str = ComputeLabelChoose(j, True, False)
str = ComputeLabelChoose(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelChoose(ByVal Action As Integer, ByVal IsHeld As Boolean, ByVal IsConditional As Boolean) As String
Dim Status As String = ""
Select Case Action
Case 0, 5
Return ""
Case 1 To 11
Status = Choose(Action, "Cancelled", "Discontinued", "Suspended", _
"Unsuspended", "Collected", "Released from Hold", "Modified", _
"Discontinued for the Future", "Verified", "Modified And Verified")
Case 12
If IsConditional Then
Return "Hold Conditional Cancelled"
ElseIf IsHeld Then
Return "Hold Held Cancelled"
Else
Return "Hold Cancelled"
End If
Case Else
Return ""
End Select
If IsConditional Then Return "Conditional " & Status
If IsHeld Then Return "Held " & Status
Return Status
End Function
Sub ComputeLabelsBigArray()
OrderLabelsBigArray = New String() {"", "Cancelled", "Discontinued", "Suspended", "Unsuspended", "", "Collected", "Released from Hold", "Modified", "Discontinued for the Future", "Verified", "Modified And Verified", "Hold Cancelled", _
"", "Conditional Cancelled", "Conditional Discontinued", "Conditional Suspended", "Conditional Unsuspended", "Conditional ", "Conditional Collected", "Conditional Released from Hold", "Conditional Modified", "Conditional Discontinued for the Future", "Conditional Verified", "Conditional Modified And Verified", "Hold Cancelled", _
"", "Held Cancelled", "Held Discontinued", "Held Suspended", "Held Unsuspended", "Held ", "Held Collected", "Held Released from Hold", "Held Modified", "Held Discontinued for the Future", "Held Verified", "Held Modified And Verified", "Hold Cancelled"}
Dim str As String = ""
For i As Integer = 0 To 1000000
For j As Integer = -1 To 13
str = ComputeLabelChoose(j, False, False)
str = ComputeLabelChoose(j, True, False)
str = ComputeLabelChoose(j, False, True)
Next
Next
End Sub
Public Function ComputeLabelBigArray(ByVal Action As Integer, ByVal IsHeld As Boolean, ByVal IsConditional As Boolean) As String
If Action < 0 OrElse Action >= 13 Then Return ""
Return OrderLabelsBigArray(Action - IsConditional * 13 - (IsHeld AndAlso Not IsConditional) * 26)
End Function
End Module
Теперь, если я совершил еще одну ошибку, кто-то может помочь найти ее.