名站导航为爱好php程序的朋友们提供php相关的教程知识。
hash Table是PhP程序的核心,这话一点都不过分。PhP程序的数组、关联数组、对象属性、函数表、符号表等等都是用hashTable来做为容器的。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
PhP程序的hashTable采用的拉链法来解决冲突,这个自不用多说,我今天主要关注的就是PhP程序的hash算法,和这个算法本身透露出来的一些思想。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
PhP程序的hash采用的是目前最为普遍的DJBX33A (Daniel J. Bernstein, Times 33 with Addition),这个算法被广泛运用与多个软件项目,Apache、Perl和Berkeley DB等。对于字符串而言这是目前所知道的最好的哈希算法,原因在于该算法的速度非常快,而且分类非常好(冲突小,分布均匀)。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
算法的核心思想就是:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash(i) = hash(i-1) * 33 str[i]rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
在zend_hash.h中,我们可以找到在PhP程序中的这个算法:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
static inline ulong zend_inline_hash_func(char *arKey, uint nKeyLength)rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
{rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
register ulong hash = 5381;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
/* variant with the hash unrolled eight times */rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
for (; nKeyLength >= 8; nKeyLength -= 8) {rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash = ((hash << 5) hash) *arKey ;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
}rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
switch (nKeyLength) {rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 7: hash = ((hash << 5) hash) *arKey ; /* fallthrough... */rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 6: hash = ((hash << 5) hash) *arKey ; /* fallthrough... */rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 5: hash = ((hash << 5) hash) *arKey ; /* fallthrough... */rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 4: hash = ((hash << 5) hash) *arKey ; /* fallthrough... */rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 3: hash = ((hash << 5) hash) *arKey ; /* fallthrough... */rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 2: hash = ((hash << 5) hash) *arKey ; /* fallthrough... */rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 1: hash = ((hash << 5) hash) *arKey ; break;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
case 0: break;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
EMPTY_SWITCh_DEFAULT_CASE()rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
}rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
return hash;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
}rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
相比在Apache和Perl中直接采用的经典Times 33算法:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hashing function used in Perl 5.005:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
# Return the hashed value of a string: $hash = perlhash("key")rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
# (Defined by the PERL_hASh macro in hv.h)rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
sub perlhashrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
{rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
$hash = 0;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
foreach (split //, shift) {rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
$hash = $hash*33 ord($_);rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
}rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
return $hash;rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
}rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
在PhP程序的hash算法中,我们可以看出很处细致的不同。首先,最不一样的就是,PhP程序中并没有使用直接乘33,而是采用了:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
hash << 5 hashrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
这样当然会比用乘快了。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
然后,特别要主意的就是使用的unrolled,我前几天看过一篇文章讲Discuz的缓存机制,其中就有一条说是Discuz会根据帖子的热度不同采用不同的缓存策略,根据用户习惯,而只缓存帖子的第一页(因为很少有人会翻帖子)。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
于此类似的思想,PhP程序鼓励8位一下的字符索引,他以8为单位使用unrolled来提高效率,这不得不说也是个很细节的,很细致的地方。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
另外还有inline,register变量 … 可以看出PhP程序的开发者在hash的优化上也是煞费苦心。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
最后就是,hash的初始值设置成了5381,相比在Apache中的times算法和Perl中的hash算法(都采用初始hash为0),为什么选5381呢?具体的原因我也不知道,但是我发现了5381的一些特性:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
Magic Constant 5381:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
1. odd numberrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
2. prime numberrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
3. deficient numberrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
4. 001/010/100/000/101 brEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
看了这些,我有理由相信这个初始值的选定能提供更好的分类。rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
至于说,为什么是Times 33而不是Times 其他数字,在PhP程序 hash算法的注释中也有一些说明,希望对有兴趣的同学有用:rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
DJBX33A (Daniel J. Bernstein, Times 33 with Addition)rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
This is Daniel J. Bernstein's popular `times 33' hash function asrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
posted by him years ago on comp.lang.c. It basically uses a functionrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
like ``hash(i) = hash(i-1) * 33 str[i]''. This is one of the bestrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
known hash functions for strings. Because it is both computed veryrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
fast and distributes very well.rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
The magic of number 33, i.e. why it works better than many otherrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
constants, prime or not, has never been adequately explained byrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
anyone. So I try an explanation: if one experimentally tests allrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
multipliers between 1 and 256 (as RSE did now) one detects that evenrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
numbers are not useable at all. The remaining 128 odd numbersrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
(except for the number 1) work more or less all equally well. TheyrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
all distribute in an acceptable way and this way fill a hash tablerEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
with an average percent of approx. 86%.rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
If one compares the Chi^2 values of the variants, the number 33 notrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
even has the best value. But the number 33 and a few other equallyrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
good numbers like 17, 31, 63, 127 and 129 have nevertheless a greatrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
advantage to the remaining numbers in the large set of possiblerEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
multipliers: their multiply operation can be replaced by a fasterrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
operation based on just one shift plus either a single additionrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
or subtraction operation. And because a hash function has to bothrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
distribute good _and_ has to be very fast to compute, those fewrEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
numbers should be preferred and seems to be the reason why Daniel J.rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
Bernstein also preferred it.rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
-- Ralf S. Engelschall <rse@engelschall.com>rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
名站网址导航
PhP程序内核探索:翻译一篇hashTables文章rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
rEqAIChat_企业网址导航_网址分类目录_企业黄页网址提交查询专业网站!
好了关于php程序的知识就说到这里希望可以帮助需要的朋友。,