如何简化和优化此校验和代码?

时间:2011-01-27 03:53:43

标签: vb.net algorithm performance optimization checksum

好的,这段代码有效,但我认为中间有一些必要的步骤可以达到目的。有关如何使其更紧的任何想法?

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

BTW这就是我用来测试它的方法:

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 个答案:

答案 0 :(得分:2)

老实说,我不确定为什么要浪费时间来优化它。在循环中调用该函数超过100,000次需要小于20毫秒。即使这是您应用程序中的“热点”之一(因为您说它与嵌入式硬件设备通信),通过优化您的代码,您不太可能看到任何明显的速度提升。

但只是为了好玩,我决定看看我是不是可以稍微优化一下......这就是我想出的:

  1. 删除多余的List(Of Char)创建。您已经使用ToCharArray方法将值转换为数组。为什么要花费ToList来调用它,只是为了迭代它?您也可以通过数组进行迭代。这样可以将时间减少到大约8秒,这是一个非常大的速度,只需很少的努力。

  2. 您还可以将新List(Of Byte)的大致大小作为参数传递给构造函数。您已经从charArray的大小知道了这一点,因为您只是将这些元素添加回来。当您只使用两个项目时,这没有任何区别,例如您提供,但它可以使更大的元素数量更有效,因为List不必在循环期间的任何点动态调整大小。

  3. AscAscWConvert.ToInt32之间绝对没有区别。我明确地测量了它们中的每一个。我的直觉是将其改为AscW,但显然无所谓。很多人会因使用特定于VB的习语而嗤之以鼻,并推荐他们认为.NET Framework提供的更通用的方法。事实证明,由于所有特定于VB的代码都是在与备选方案相同的托管代码中编写的,因此您可以使用它来简单地优先考虑。

  4. 否则用简单数组替换List(Of T)也不会产生任何明显的差异。由于List更容易在函数外部使用,因此您可以将其保留为返回的类型。

  5. 所以我的最终代码看起来像这样:

    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进行编程。 但你应该是。你必须在项目的属性中明确设置选项,但强类型的好处远远超过了完成和修复现有代码的成本。您甚至可能会注意到性能提升,特别是如果您无意中使用了大量后期绑定。