Оптимизация функций VB.Net (отчетный код SSRS) - PullRequest
0 голосов
/ 14 января 2010

Недавно я наткнулся на следующий код и хотел бы его оптимизировать:

Public Shared Function ComputeLabel(ByVal Action As Integer, ByVal Flag1 As Boolean, ByVal Flag2 As Boolean) As String
   Dim Prefix As String = ""

   If Flag2 Then
      Prefix = "Conditional "
   ElseIf Flag1 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

Обратите внимание, что действие 0 является наиболее распространенным случаем.

Хорошо, я уже немного очистил эту функцию - она ​​использовала переменную и возвращала ее в конце, а использование Return кажется лучше. Но, кроме того, я думаю, что было бы лучше создать код в начале выполнения отчета, а затем просто обращаться к элементам массива каждый раз, когда вызывается эта функция, вместо использования оператора Select. Но случай 12 усложняет ситуацию (как вы можете видеть, он добавляет префикс в середине, а не в начале).

Как вы думаете, что будет лучшим способом:

  • Одноразовое построение массива из 39 элементов для трех случаев:

    Private Shared OrderActions() As String = {"", "Cancelled", ...}
    

    Тогда в функции, обращающейся к нему, вот так:

    If Action < 0 OrElse Action >= 13 Then Return ""
    Return OrderActions(Action - Flag2 * 13 - (Flag1 AndAlso Not Flag2) * 26)
    
  • Использование массива из 13 элементов с заменой (что-то вроде Return Replace(LabelList(Action), "{Prefix}", Prefix)?)

  • Использование массива из 12 элементов со специальным регистром для действия 12.

  • Что-то еще, о чем я не думал.

Обновление 1: мое форматирование было отключено, поэтому параметры могли быть неясными. Теперь он должен быть более читабельным.

Обновление 2: я понимаю, что вы имеете в виду, что с точки зрения производительности полное расширение всех случаев и использование простого назначения переменных, вероятно, быстрее всего. Итак ... скажем, максимальная скорость не является приоритетом, но общая элегантность (сочетание чистого кода и скорости). Есть ли шанс, что люди тоже могут это принять? Я буду голосовать за всех, кто окажет разумную помощь по всем аспектам вопроса.

Обновление 3. Еще одно соображение, которое я проигнорировал, заключается в том, что некоторые неопытные программисты будут поддерживать этот долгосрочный подход, поэтому его должно быть легко понять. Полагаю, мои примеры попыток сократить код действительно не годятся с этой точки зрения.

Обновление 4: ИСПЫТАНИЯ - КОРОЛЬ ВСЕМ !!! После того, как меня вдохновили на тесты скорости, я получил интересные результаты. Смотрите мой ответ ниже.

Ответы [ 6 ]

2 голосов
/ 14 января 2010

Что ж, если это узкое место и скорость является приоритетом, то мое первое предложение - устранить конкатенацию строк, дублируя большую часть вашей логики. Это сделает функцию больше и менее читабельной, но, возможно, она того стоит для скорости ...

Public Shared Function ComputeLabel(ByVal Action As Integer, ByVal Flag1 As Boolean, ByVal Flag2 As Boolean) As String
   Select Case nHVCOrderAction
        Case 0
            Return ""
        Case 1
            If Flag2 Then
                Return "Conditional Cancelled"
            ElseIf Flag1 Then
                Return "Held Cancelled"
            Else
                Return "Cancelled"
            End If
        Case 2
            If Flag2 Then
                Return "Conditional Discontinued"
            ElseIf Flag1 Then
                Return "Held Discontinued"
            Else
                Return "Discontinued"
            End If
        ' And so on...
   End Select
End Function

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

UPDATE:

Я написал быстрое и грязное консольное приложение VB.NET, чтобы проверить ваш оригинальный код против моего. Вот цикл, который я запускал для каждой (я не писал все возможные комбинации, но вы поняли):

    Dim sw As New Stopwatch()
    sw.Start()

    For i As Integer = 0 To 10000000
        str = ComputeLabel(0, True, False)
        str = ComputeLabel(1, False, False)
        str = ComputeLabel(0, False, False)
        str = ComputeLabel(2, False, False)
        str = ComputeLabel(1, False, True)
        str = ComputeLabel(2, True, True)
        str = ComputeLabel(4, False, True)
        str = ComputeLabel(7, True, True)
        str = ComputeLabel(12, False, True)
    Next

    sw.Stop()
    Console.WriteLine(sw.ElapsedMilliseconds & " ms")

А вот времена:

Старый метод: 6189 мс

Новый метод: 1374 мс

Таким образом, в 5 раз улучшено быстродействие за счет удаления конкатенации строк и расширения условий для каждого случая. Конечно, как вы могли заметить, цикл повторяется 10 миллионов раз ... это много.

UPDATE:

Я написал другое тестовое приложение, чтобы точно имитировать ваше собственное:

Module Module1

        Sub Main()

            Dim str As String = ""
            Dim sw As New Stopwatch()

            ' Test 1
            sw.Start()
            For i As Integer = 0 To 100000
                 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
            sw.Stop()
            Console.WriteLine("Old method: " & sw.ElapsedMilliseconds & " ms")
            sw.Reset()

            ' Test 2
            sw.Start()
            For i As Integer = 0 To 100000
                 For j As Integer = -1 To 13
                        str = ComputeLabel_Y(j, False, False)
                        str = ComputeLabel_Y(j, True, False)
                        str = ComputeLabel_Y(j, False, True)
                 Next
            Next
            sw.Stop()
            Console.WriteLine("New method: " & sw.ElapsedMilliseconds & " ms")
            sw.Reset()

        End Sub

        Public Function ComputeLabel_X(ByVal Action As Integer, ByVal Held As Boolean, ByVal Conditional As Boolean) As String
             Dim Prefix As String = ""

             If Conditional Then
                    Prefix = "Conditional "
             ElseIf Held 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

        Public Function ComputeLabel_Y(ByVal Action As Integer, ByVal Held As Boolean, ByVal Conditional As Boolean) As String
             Select Case Action
                    Case 0
                        Return ""
                    Case 1
                        If Conditional Then
                            Return "Conditional Cancelled"
                        ElseIf Held Then
                            Return "Held Cancelled"
                        Else
                            Return "Cancelled"
                        End If
                    Case 2
                        If Conditional Then
                            Return "Conditional Discontinued"
                        ElseIf Held Then
                            Return "Held Discontinued"
                        Else
                            Return "Discontinued"
                        End If
                    Case 3
                        If Conditional Then
                            Return "Conditional Suspended"
                        ElseIf Held Then
                            Return "Held Suspended"
                        Else
                            Return "Suspended"
                        End If
                    Case 4
                        If Conditional Then
                            Return "Conditional Unsuspended"
                        ElseIf Held Then
                            Return "Held Unsuspended"
                        Else
                            Return "Unsuspended"
                        End If
                    Case 6
                        If Conditional Then
                            Return "Conditional Collected"
                        ElseIf Held Then
                            Return "Held Collected"
                        Else
                            Return "Collected"
                        End If
                    Case 7
                        If Conditional Then
                            Return "Conditional Released from Hold"
                        ElseIf Held Then
                            Return "Held Released from Hold"
                        Else
                            Return "Released from Hold"
                        End If
                    Case 8
                        If Conditional Then
                            Return "Conditional Modified"
                        ElseIf Held Then
                            Return "Held Modified"
                        Else
                            Return "Modified"
                        End If
                    Case 9
                        If Conditional Then
                            Return "Conditional Discontinued for the Future"
                        ElseIf Held Then
                            Return "Held Discontinued for the Future"
                        Else
                            Return "Discontinued for the Future"
                        End If
                    Case 10
                        If Conditional Then
                            Return "Conditional Verified"
                        ElseIf Held Then
                            Return "Held Verified"
                        Else
                            Return "Verified"
                        End If
                    Case 11
                        If Conditional Then
                            Return "Conditional Modified And Verified"
                        ElseIf Held Then
                            Return "Held Modified And Verified"
                        Else
                            Return "Modified And Verified"
                        End If
                    Case 12
                        If Conditional Then
                            Return "Hold Conditional Cancelled"
                        ElseIf Held Then
                            Return "Hold Held Cancelled"
                        Else
                            Return "Hold Cancelled"
                        End If
                    Case Else
                        Return ""
             End Select
        End Function
End Module

И мои результаты снова намного быстрее с моим кодом:

Старый метод: 169 мс

Новый метод: 30 мс

Я, конечно, работаю без отладки (Ctrl F5). А теперь я использую четырехъядерный процессор AMD с тактовой частотой 3,0 ГГц.

1 голос
/ 16 января 2010

Вот результаты моего собственного тестирования скорости (наконец).

В своих тестах я использовал следующий код. Я использовал 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

Теперь, если я совершил еще одну ошибку, кто-то может помочь найти ее.

1 голос
/ 16 января 2010

На самом деле, если вы поместите их в массивы, это увеличит время выполнения с 6589 мс на моей машине до 1174 мс, используя следующий метод:

Ниже из консольного приложения, но вы получите общее представление. Массивы загружаются один раз, затем к ним обращаются столько раз, сколько вы хотите, в этом случае я использовал цикл for, который Стив Уортам опубликовал в качестве теста.

Dim _ConditionalLabels(12) As String
Dim _HeldLabels(12) As String

Sub Main()
    Dim sw As New Stopwatch()
    sw.Start()

    _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 10000000
        str = ComputeLabel(0, True, False)
        str = ComputeLabel(1, False, False)
        str = ComputeLabel(0, False, False)
        str = ComputeLabel(2, False, False)
        str = ComputeLabel(1, False, True)
        str = ComputeLabel(2, True, True)
        str = ComputeLabel(4, False, True)
        str = ComputeLabel(7, True, True)
        str = ComputeLabel(12, False, True)
    Next

    sw.Stop()
    Console.WriteLine(sw.ElapsedMilliseconds & " ms")
    Console.Read()
End Sub

Public Function ComputeLabel(ByVal Action As Integer, ByVal Held As Boolean, ByVal Conditional As Boolean) As String
    If Conditional Then
        Return _ConditionalLabels(Action)
    ElseIf Held Then
        Return _HeldLabels(Action)
    End If
End Function
1 голос
/ 14 января 2010

Вы не можете оптимизировать это, это уже очень эффективно. Вы можете сделать его более читабельным, хотя Flag1 и Flag2 определенно должны быть переименованы в Held и Conditional.

0 голосов
/ 16 января 2010

Есть мысли по поводу этой версии?

Public Shared Function ComputeLabel(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

или это?

Public Shared Function ComputeLabel(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

Я подозреваю, что функция выбора может быть очень медленной ...

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

0 голосов
/ 14 января 2010

Стив Уортам уже сказал самое важное: единственная неэффективная часть вашей функции - это конкатенация строк. Если вам действительно нужна эта функция для быстрой работы, не обращайте внимания на длину исходного кода и явно расширяйте каждый случай, чтобы избежать объединения строк.

Я хотел бы добавить одну вещь: использование массива не поможет вам оптимизировать функцию. .NET-массивы не являются массивами C, это сложные объекты, которые должны быть построены, заполнены данными и уничтожены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...