注意:我不是在尝试使用SuperFastHash并期望它提供与CRC32相同的输出值。
我正在编写一个简单的LZSS压缩/解压缩例程,以提供非常快速的解压缩,并且在解压缩时没有内存开销。输入数据分为4096字节长的块,并顺序压缩。
我的问题:我想为每个压缩块(块大小
经过一些测试,我发现关于项目约束,CRC32太慢了。我从here使用了enwik9(维基百科的10 ^ 9字节文本转储)。我使用LZSS例程对其进行了压缩,并获得了570Mb文件。我测量了以下持续时间(单线程,不包括磁盘IO,所有数据在处理之前已加载到内存中,平均10次试验):
| Operation | Time (GCC4.4.5/Linux) | Time (MSVC2010/Win7) | |-------------------------------+--------------------------+------------------------| | Decompression | 6.8 seconds | 6.95 seconds | | CRC32 on decompressed result | 4.9 seconds | 4.62 seconds | | CRC32 on compressed result | 2.8 seconds | 2.69 seconds |
Then I tested SuperFastHash, just by curiosity :
| Operation | Time (GCC4.4.5/Linux) | Time (MSVC2010/Win7) | |-------------------------------+--------------------------+------------------------| | SFH on decompressed result | 1.1 seconds | 1.33 seconds | | SFH on compressed result | 0.7 seconds | 0.75 seconds |
And here is my CRC32 implementation (I followed the descriptions from the following document : http://www.ross.net/crc/download/crc_v3.txt) :
# include <stdint.h>
// CRC32 lookup table (corresponding to the polynom 0x04C11DB7)
static const uint32_t crc32_lookup_table[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
// many lines skipped
// ...
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
} ;
uint32_t crc32_hash(const uint8_t * data, size_t len)
{
uint32_t crc32_register = 0xFFFFFFFF ;
while( len-- )
{
crc32_register = (crc32_register >> 8)
^ crc32_lookup_table[(crc32_register & 0x000000FF) ^ *data++] ;
}
return crc32_register ^ 0xFFFFFFFF ;
}
我的问题是:
我可以使用哈希而不是循环冗余校验值在压缩数据块中执行错误检测吗?据我所知(我记得在我的电子课程中),CRC算法旨在
当数据在嘈杂的通道上传输时,如果突发中发生错误,则效率非常高,而从硬盘驱动器读取数据则不是这种情况。如果我错了,请纠正我。
感谢您的任何建议!
最佳答案
由于问题不关乎安全性,因此可以使用“破损”的加密哈希函数,这些函数对于有意识的攻击者而言并不安全,但在检测传输错误方面仍然非常出色。我在考虑MD4,在某些平台上,它被认为比CRC32更快。您可能还需要检查RadioGatún和巴拿马;有关各种加密哈希函数在C和Java中的开源实现,请参见this library。
如果您的目标体系结构是具有AES-NI指令的最新/足够大的x86 CPU,那么您可以通过简单地使用块密码AES和常规密钥(例如,全部)来计算CBC-MAC,从而以惊人的速度实现非常好的校验和-零键);由于这不是出于安全考虑,因此您甚至可以使用少于标准AES的回合数(例如,使用5回合而不是标准的10回合)。