除了性能和安全性考虑之外,并假设具有完美雪崩效果的哈希函数,我应该使用该函数对数据块进行校验和:CRC32或哈希被截断为N个字节吗? IE。哪个有较小的机会错过错误?具体来说:

  • CRC32与4字节哈希
  • CRC32与8字节哈希
  • CRC64与8字节哈希

  • 数据块将通过网络重复传输并存储在磁盘上。块的大小可以在1KB到1GB之间。

    据我了解,CRC32最多可以100%的可靠性检测到32位翻转,但是此后其可靠性接近1-2^(-32),对于某些模式,它的可靠性更差。完美的4字节哈希可靠性始终是1-2^(-32),所以去吧。

    8字节的散列应该具有更好的整体可靠性(2^(-64)可能会漏掉一个错误),因此它应优先于CRC32吗? CRC64呢?

    我猜答案取决于这种操作中可能预期的错误类型。我们可能会看到稀疏的1位翻转或大量的块损坏吗?此外,鉴于大多数存储和网络硬件都实现了某种CRC,是否应该已经解决了意外的位翻转问题?

    最佳答案

    只有您可以说1-2-32对于您的应用程序是否足够好。一个好的哈希函数在CRC-n位和n位之间的错误检测性能将非常接近,因此请选择速度更快的一个。可能是CRC-n。

    更新:

    上面的“可能是CRC-n”只是有点可能。如果使用非常高性能的哈希函数,则不太可能。特别是,CityHash看起来几乎与使用英特尔crc32硬件指令计算出的CRC-32一样快!我在434 MB的文件上测试了三个CityHash例程和Intel crc32指令。 crc32指令版本(用于计算CRC-32C)花费了24毫秒的CPU时间。 CityHash64花费了55毫秒,CityHash128花费了60毫秒,CityHashCrc128花费了50毫秒。 CityHashCrc128使用相同的硬件指令,尽管它不计算CRC。

    为了快速进行CRC-32C计算,我不得不在三个单独的缓冲区上使用三个crc32指令,以便在单个内核中并行使用三个算术逻辑单元,然后在其中编写内部循环汇编器。 CityHash很快就该死了。如果您没有crc32指令,那么您将很难计算出与CityHash64或CityHash128一样快的32位CRC。

    但是请注意,为此目的需要修改CityHash函数,或者需要做出任意选择,以便为大型数据流上的CityHash值定义一致的含义。原因是这些功能未设置为接受缓冲的数据,即一次将功能块送入一个块,并希望获得与将整个数据集立即送入该功能相同的结果。需要修改CityHash函数以更新中间状态。

    替代方法以及我为进行快速而肮脏的测试所做的工作是使用函数的Seed版本,在该版本中,我将使用前一个缓冲区中的CityHash作为下一个缓冲区的种子。问题在于结果取决于缓冲区大小。如果使用这种方法为CityHash提供不同大小的缓冲区,则将获得不同的哈希值。

    四年后的另一个更新:

    xxhash family甚至更快。我现在建议通过CRC进行非加密哈希。

    关于hash - 校验和: CRC or hash?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14536130/

    10-12 19:15