我正在使用以下函数来计算VS2008,.NET 3.5项目中文件的CRC32:
public UInt32 ComputeHash(System.IO.Stream stream)
{
unchecked
{
const int BUFFER_SIZE = 1024;
UInt32 crc32Result = 0xFFFFFFFF;
byte[] buffer = new byte[BUFFER_SIZE];
int count = stream.Read(buffer, 0, BUFFER_SIZE);
while (count > 0)
{
for (int i = 0; i < count; i++)
{
crc32Result = ((crc32Result) >> 8) ^ _crc32Table[(buffer[i]) ^ (crc32Result) & _LOOKUP_TABLE_MAX_INDEX];
}
count = stream.Read(buffer, 0, BUFFER_SIZE);
}
return ~crc32Result;
}
}
Run Code Online (Sandbox Code Playgroud)
为简洁起见,我遗漏了构建查找表(_crc32Table)的函数.该表是一个UInt32数组,是在实例化类时构建的,包含256个值(256也是_LOOKUP_TABLE_MAX_INDEX + 1的值).
我已经运行了一些基准测试,将它与MD5CryptoServiceProvider和SHA1CryptoServiceProvider ComputeHash函数进行比较,它们的速度要快得多.MD5功能的速度提高了两倍,SHA1哈希的速度提高了约35%.我被告知CRC32很快,但那不是我所看到的.
我错误地假设了吗?这是预期的还是这个算法有缺陷?
您正在将代码与内置函数进行比较,并询问它们为何更快.您需要做的是找到内置函数的源代码.他们是如何工作的?看看有什么不同.
Betcha内置函数调用本机库并且不必在托管内存框架内运行就作弊.
也许:您在观察 CRC 吞吐量时是否计算了查找表的计算?通常,查找表计算一次并缓存。如果不缓存它,那么每次计算 CRC 时都会计算它。另外,如果您只测量一个 CRC,那么您可能已将表计算成本包含在 CRC 计算成本中。最好测量每个哈希的多次迭代。
附录:当我测量时,当使用 /debug+ 和 /optimize- 编译应用程序时,将 CRC32 与 MD5 哈希进行比较,我发现系数为 2.6 倍。使用 /debug- 和 /optimize+,我看到了 1.6 倍的系数。当我更改编译标志时,绝对 MD5 性能没有变化。在没有调试的情况下,CRC 仍然较慢,但已经接近得多。