用于路径缓存的快速、无冲突哈希算法?
Posted
技术标签:
【中文标题】用于路径缓存的快速、无冲突哈希算法?【英文标题】:fast, collisionless hash algorithm for path caching? 【发布时间】:2011-11-12 12:39:04 【问题描述】:我正在使用 php 转换网站。我的部分过程是验证图像路径不指向不存在的图像(即没有损坏的图像)。由于许多页面共享某些图像,因此我设置了一个缓存数组以查看我是否已经检查了给定路径的图像文件是否存在。
使用原始路径字符串作为数组索引不起作用,所以我使用了md5()
,这样就可以了。但是,转换脚本需要很长时间,而且很明显这是因为 md5 计算(过去几天我一直在频繁运行转换,我马上注意到我的缓存开始工作,脚本需要更长的时间才能运行。)
所以我想知道是否有一种更快的哈希算法可以在我的缓存中使用,当然我需要一种不会产生冲突的算法。由于这是一个一次性脚本,我不需要一个超级安全的牢不可破的算法,只需要一个能更快完成工作的算法。
This comment 显然是 php 可用的所有散列函数的列表。
编辑我在评论中并没有引起太多关注,但是当我使用路径的纯字符串作为缓存数组的索引时,它不起作用。一旦我将其更改为 md5 哈希,它就起作用了。如果我有更多的时间,我会解决这个问题,但这是一个一次性的项目,我不能花比我绝对必须的时间更多的时间。
发布编辑好的,显然我的缓存做错了;当我将索引更改为导致缓存开始工作的散列时,无论散列如何,我一定改变了一些东西。人们说我的散列应该可以用于文件路径字符串,而且 md5s 无论如何也不会花那么长时间。所以,我不知道自己做错了什么,也没有时间在这个项目中弄清楚。我会删除这个问题,但它已经有了答案。
【问题讨论】:
不存在无冲突哈希。散列本质上涉及获取无限数量的输入,并将它们映射到有限数量的输出。即使在有限的数据集上(当然,大小 > 1),也无法保证 任何 哈希算法在不实际对所有哈希算法进行哈希并检查冲突的情况下避免冲突。 如果 MD5 太慢,你就做错了。过去 5 年建造的任何机器都应该能够每秒散列数百万条路径。您管理阵列的方式很可能很慢。问题根本不可能是 MD5。 @Michael Madsen 它必须是无碰撞的足够。 @user151841:现在您只需定义哈希算法何时“足够无冲突”。 :) 如果这意味着“我的数据集中最多有 X 次冲突”之类的东西 - 那么,任何哈希算法很可能仍然值得使用(并且可能许多算法不值得使用!)满足这个需求,但如果没有测试,你就无法知道这一点。 您是否考虑过布隆过滤器(它似乎非常适合您表达的任务)? 【参考方案1】:如果这些哈希值仅在 PHP 内部使用,并且是在此脚本运行时动态构建的,为什么不简单地使用数组?
if (isset($path_cache['/some/weird/ugly/long/path']))
...
在没有 MD5 计算开销的情况下也能正常工作。
【讨论】:
我会仔细检查我是否有更多时间,但无论出于何种原因,使用原始路径字符串作为数组索引不起作用(我在我的问题中说过)。当我使用散列字符串作为索引时,它起作用了。 怎么没用?如果用作键的字符串是路径还是 md5 哈希,PHP 不在乎 - 它们都只是字符串。 以下是它不起作用的原因:我将它设置为在从缓存数组中提取值时抛出一条消息。在过去的一周里,我还没有看到这条消息,即使缓存中充满了路径。我将索引更改为哈希,突然之间,几乎所有内容都从缓存中出来了。不幸的是,我没有时间弄清楚我做错了什么:P【参考方案2】:我建议您为此使用普通路径 - 无需对其进行哈希处理。但是,crc32
似乎很快。请记住 - 您正在牺牲碰撞率来换取速度。
【讨论】:
【参考方案3】:最快的哈希函数似乎是
hash('adler32', $string);
不过,md5()
的运行速度几乎与上述函数一样快。
PHP 中有所有可用哈希的基准测试。http://l.garygolden.me/fastest-hash-php
【讨论】:
【参考方案4】:foreach (hash_algos() as $value)
print hash($value, 'some random') . ' - ' . $value . '<br />';
它将打印在 php 支持的所有散列算法中散列的字符串。
【讨论】:
以上是关于用于路径缓存的快速、无冲突哈希算法?的主要内容,如果未能解决你的问题,请参考以下文章