转载(全文)地址:http://blog.csdn.net/zajin/article/details/12648587 最先进的非加密散列函数在过去几年中得到了快速推广。当我这周搜索的时候,我很高兴的看到新的尖端散列函数已经发布即使上次我进行这个方面的搜索是6个月到1年前的事情了。 非加密散列函数将字符串作为输入,通过计算输出一个整数。理想的散列函数的一个特性是输出非常均匀分布在可能的输出域,特别是当输入非常相似的时候。不同于加密散列函数,这些函数不是为防止攻击者找出碰撞而设计的。加密散列函数有这个特性但是要慢的多: SHA-1大约为0.09 bytes/cycle,而最新的非加密散列函数的速度大约为3 bytes/cycle。所以在不考虑抵御攻击的成本下,非加密散列大约要快33倍。非加密散列函数用的最多的地方是hash table。 |
一个有趣的题外话,现在Lua社区上有个关于针对Lua的散列函数理论上可以被攻击使得hash table最坏情况下的查找复杂度降低到O(n) 的事实我们应该做些什么(如果可以的话)的争论,如果攻击者引导你输入你放入lua hash table的东西,那么他可以通过DoS攻击你。Lua的作者怀疑这种攻击实施的可行性(以及它的代价是否比其他DoS攻击更小),但是他还是打算在将要使用的散列函数的开始时候生成随机种子。这是一个有趣的加密替代函数,能够给你与加密散列函数相同的耐碰撞能力(假设你有能够给你真正随机位的信息源),但这将以非重复性输出为代价。 由于非加密散列函数有很多种选择,并且可供选择的数目不断扩大,我想我应该总结以下我对这个领域的了解。 |
另一个需要考虑的是对齐和非对齐的访问。Murmur散列(不像City或者Spooky)是一个仅能进行对齐读取的变种,因为在很多架构上非对齐的读取会崩溃或者返回错误的数据(非对齐的读取操作在C中是未定义的行为)。City和Spooky都强调使用memcpy()把输入数据复制到对齐的存储结构中;Spooky使用一次memcpy()操作一个块(如果ALLOW_UNALIGNED_READS未定义),City使用一次memcpy()操作一个整型!在可以处理非对称读取的机器上(像x86和x86-64),memcpy将被优化,但我在我的小ARM上做了一个测试,发现如下:
编译这段低效的代码(在x86上是一个单独的操作):
结论是,如果你需要32位或者仅仅是对齐读取的话,Murmur散列看起来依旧是最好的选择。City散列和Spooky散列在x86-64上看起来更快,但我更倾向于认为它们是特定用于那个架构的,因为我不知道是否有其他既是64位又允许非对其读取的架构。 文中若有谬误,敬请告知。 |