The first thought was "为什么他不使用一个简单的md5函数呢?"。
尝试自己编写哈希函数
其中一个
最常用的函数是一个简单的哈希函数
Bernstein's function,也称为
Times 33 with Addition
。它在
php
中被zend
用于为关联数组的键生成哈希值。在
php
中可以这样实现:
function djb2($s){
$word = str_split($s);
$length = count($word);
$hashAddress = 5381;
for ($counter = 0; $counter < $length; $counter++){
$hashAddress = (($hashAddress << 5) + $hashAddress) + $word[$counter];
}
return $hashAddress;
}
echo djb2("stackoverflow");
问题在于,当以这种方式实现时,速度相对较慢。测试表明,它比md5
慢约3倍。因此,我们必须找到最快的内部实现hash
函数。
寻找最佳的内部哈希函数
只需使用所有算法并测量哈希一百万个字符串所需的时间即可。
function testing($algo, $str) {
$start = microtime(true);
for($ax = 0; $ax < 1000000; $ax++){
hash($algo, $str);
}
$end = microtime(true);
return ($end - $start);
}
$algos = hash_algos();
$times = [];
foreach($algos as $algo){
$times[$algo] = testing($algo, "stackoverflow");
}
// sort by time ASC
asort($times);
foreach($times as $algo => $time){
echo "$algo -> " . round($time, 2)."sec\n";
}
我的结果是:
fnv1a32 -> 0.29sec
fnv132 -> 0.3sec
crc32b -> 0.3sec
adler32 -> 0.3sec
crc32 -> 0.31sec
joaat -> 0.31sec
fnv1a64 -> 0.31sec
fnv164 -> 0.31sec
md4 -> 0.46sec
md5 -> 0.54sec
...
md2 -> 6.32sec
结果会略有变化 - 前8个算法由于速度接近并且依赖于服务器负载而进行洗牌。
应该选择什么?
您可以选择上面任何一个顶级函数:
$hash = hash('crc32', $string);
。实际上,广泛使用的
md5
函数只比领先者慢1.7倍。
奖励
还有其他像SuperFastHash这样的函数, 它们没有在
php
代码中实现,但比
crc32
快4倍。