开发者

How can I simplify and optimize this checksumming code?

Ok this code works but I think it has some necessary steps in the middle to get to the outcome. Any thoughts on how to make it tighter?

Public Function CalCheckSum(ByVal By开发者_Python百科teList 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

BTW This is what I'm using to test it:

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)

The correct values for b are:

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


I'm honestly not sure why you'd waste the time it takes to optimize this. Calling that function over 100,000 times in a loop takes less than 20 milliseconds. Even if this is one of the "hot points" in your application (since you say it communicates with an embedded hardware device), it's unlikely that you'll see any appreciable speed increase by optimizing the code that you have.

But just for fun, I decided to see if I couldn't optimize things a little anyway... Here's what I came up with:

  1. Remove the redundant List(Of Char) creation. You're already converting the values to an array with the ToCharArray method. Why go through the expense of calling ToList on that, just to iterate through it? You can iterate just as well through an array. This shaves the time down to around 8 seconds, a pretty massive speed-up for minimal effort.

  2. You can also pass in the approximate size of your new List(Of Byte) as an argument to the constructor. You already know this from the size of your charArray, since you're just adding each of those elements back in. This doesn't make any difference when you're only working with two items, as in the example you provided, but it could make things slightly more efficient for substantially larger numbers of elements because the List wouldn't have to be dynamically resized at any point during the loop.

  3. There's absolutely no difference between Asc, AscW, and Convert.ToInt32. I measured each of them explicitly just to see. My gut instinct was to change that to AscW, but apparently it doesn't matter. Lots of people will turn their nose up at the use of VB-specific idioms, and recommend what they consider more universal methods provided by the .NET Framework. It turns out that since all the VB-specific code is written in the same managed code as the alternatives, it's a simple matter of preference which you use.

  4. Otherwise replacing List(Of T) with simple arrays doesn't make any appreciable difference, either. Since a List is easier to work with outside of the function, you might as well keep it as the returned type.

So my final code looks something like this:

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

Even running this 999,000 times in a loop, I consistently clock it somewhere between 62 and 64 ms.

You could also use LINQ. It's not really my area, and I doubt you'll see any measurable speed increases (it still has to do the same amount of looping and iterating under the covers). The big benefit it provides is that your code is simpler and looks cleaner. I'm surprised someone hasn't already posted this solution.

EDIT: As an aside, your original code didn't compile for me. I had to add in the CByte operator to convert the Integer value returned from the Asc operator into a Byte type. That tells me that you're not programming with Option Strict On. But you should be. You have to explicitly set the option in your project's properties, but the benefits of strong typing far outweigh the cost of going through and fixing some of your existing code. You might even notice a performance increase, especially if you've been using a lot of late binding inadvertently.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜