Как я могу упростить и оптимизировать этот код контрольной суммы? - PullRequest
1 голос
/ 27 января 2011

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

Public Function CalCheckSum(ByVal ByteList As List(Of Byte)) As List(Of Byte)
    Dim total As Integer = 0
    For Each b As Byte In ByteList
        total = total + b

    Next
    Dim modedVal As Integer = 0
    modedVal = total Mod &H100
    Dim negatedValue As Integer = 0
    negatedValue = &H100 - modedVal
    Dim charList As List(Of Char) = Hex(negatedValue).ToCharArray.ToList
    Dim returnList As New List(Of Byte)
    For Each ch As Char In charList
        returnList.Add(Asc(ch))

    Next
    Return returnList

End Function

Кстати, вот что я использую для его проверки:

Dim blist As New List(Of Byte)
blist.Add(&H52)
blist.Add(&H34)
blist.Add(&H35)
blist.Add(&H31)
blist.Add(&H32)
blist.Add(&H33)
blist.Add(&H34)
blist.Add(&H30)

blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H30)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H46)
blist.Add(&H42)
blist.Add(&H4B)
blist.Add(&H9)
blist.Add(&H44)

Dim b As List(Of Byte) = CalCheckSum(blist)

Правильные значения для b:

  • b(0) = & H43
  • b(1) = & H39

1 Ответ

2 голосов
/ 28 января 2011

Я, честно говоря, не уверен, зачем тратить время на оптимизацию. Вызов этой функции более 100 000 раз в цикле занимает менее 20 миллисекунд . Даже если это одна из «горячих точек» в вашем приложении (поскольку вы говорите, что оно взаимодействует со встроенным аппаратным устройством), маловероятно, что вы увидите заметное увеличение скорости за счет оптимизации имеющегося кода.

Но ради интереса я решил посмотреть, не могу ли я все-таки немного оптимизировать вещи ... Вот что я придумал:

  1. Удалить избыточное List(Of Char) создание. Вы уже конвертируете значения в массив с помощью метода ToCharArray. Зачем тратить столько времени на вызов ToList, чтобы просто повторить его? Вы можете итерировать через массив. Это сокращает время примерно до 8 секунд, довольно значительное ускорение при минимальных усилиях.

  2. Вы также можете передать приблизительный размер вашего нового List(Of Byte) в качестве аргумента конструктору. Вы уже знаете это по размеру charArray, так как вы просто добавляете каждый из этих элементов обратно. Это не имеет никакого значения, когда вы работаете только с двумя элементами, как в приведенном вами примере, но это могло бы сделать вещи немного более эффективными для существенно большего числа элементов, потому что List не пришлось бы динамически изменять размер в любой точке цикла.

  3. Нет абсолютно никакой разницы между Asc, AscW и Convert.ToInt32. Я измерил каждый из них явно, чтобы увидеть. Моим инстинктивным инстинктом было изменить это на AscW, но, видимо, это не имеет значения. Многие люди обращают внимание на использование специфических для VB идиом и рекомендуют то, что они считают более универсальными методами, предоставляемыми .NET Framework. Оказывается, так как весь специфичный для VB код написан в том же управляемом коде, что и альтернативы, вы просто используете предпочтительный вопрос.

  4. В противном случае замена List(Of T) на простые массивы также не имеет существенного значения. Поскольку с List легче работать вне функции, вы можете также сохранить его как возвращаемый тип.

Итак, мой окончательный код выглядит примерно так:

Public Function CalCheckSum(ByVal ByteList As List(Of Byte)) As List(Of Byte)
    Dim total As Integer = 0
    For Each b As Byte In ByteList
        total = total + b
    Next

    Dim negatedValue As Integer = 0
    negatedValue = &H100 - (total Mod &H100)

    Dim charArray As Char() = Hex(negatedValue).ToCharArray()

    Dim returnList As New List(Of Byte)(charArray.Length)
    For Each ch As Char In charArray
        returnList.Add(CByte(Asc(ch)))
    Next

    Return returnList
End Function

Даже выполняя это 999 000 раз в цикле, я постоянно синхронизирую его где-то между 62 и 64 мс.

Вы также можете использовать LINQ . Это не совсем моя область, и я сомневаюсь, что вы заметите какое-либо измеримое увеличение скорости (все равно приходится делать то же количество циклов и итераций под крышками). Большим преимуществом является то, что ваш код проще и выглядит чище. Я удивлен, что кто-то еще не опубликовал это решение.

РЕДАКТИРОВАТЬ: Кстати, ваш исходный код не скомпилирован для меня. Мне пришлось добавить оператор CByte, чтобы преобразовать значение Integer, возвращаемое оператором Asc, в тип Byte. Это говорит о том, что вы не программируете с Option Strict On. Но вы должны быть. Вы должны явно установить опцию в свойствах вашего проекта, но преимущества строгой типизации намного перевешивают стоимость прохождения и исправления некоторого существующего кода. Вы можете даже заметить увеличение производительности, особенно если вы случайно использовали много поздних привязок.

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