php的hash算法介绍


Posted in PHP onFebruary 13, 2014

Hash Table是PHP的核心,这话一点都不过分。

PHP的数组,关联数组,对象属性,函数表,符号表,等等都是用HashTable来做为容器的。

PHP的HashTable采用的拉链法来解决冲突, 这个自不用多说, 我今天主要关注的就是PHP的Hash算法, 和这个算法本身透露出来的一些思想。

PHP的Hash采用的是目前最为普遍的DJBX33A (Daniel J. Bernstein, Times 33 with Addition), 这个算法被广泛运用与多个软件项目,Apache, Perl和Berkeley DB等. 对于字符串而言这是目前所知道的最好的哈希算法,原因在于该算法的速度非常快,而且分类非常好(冲突小,分布均匀).

算法的核心思想就是:

hash(i) = hash(i-1) * 33 + str[i]

在zend_hash.h中,我们可以找到在PHP中的这个算法:

static inline ulong zend_inline_hash_func(char *arKey, uint nKeyLength)
{
    register ulong hash = 5381;    /* variant with the hash unrolled eight times */
    for (; nKeyLength >= 8; nKeyLength -=  {
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
        hash = ((hash << 5) + hash) + *arKey++;
    }
    switch (nKeyLength) {
        case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */
        case 1: hash = ((hash << 5) + hash) + *arKey++; break;
        case 0: break;
EMPTY_SWITCH_DEFAULT_CASE()
    }
    return hash;
}

相比在Apache和Perl中直接采用的经典Times 33算法:

hashing function used in Perl 5.005:
  # Return the hashed value of a string: $hash = perlhash("key")
  # (Defined by the PERL_HASH macro in hv.h)
  sub perlhash
  {
      $hash = 0;
      foreach (split //, shift) {
          $hash = $hash*33 + ord($_);
      }
      return $hash;
  }

在PHP的hash算法中, 我们可以看出很处细致的不同.

首先, 最不一样的就是, PHP中并没有使用直接乘33, 而是采用了:

hash << 5 + hash

这样当然会比用乘快了.

然后, 特别要主意的就是使用的unrolled, 我前几天看过一片文章讲Discuz的缓存机制, 其中就有一条说是Discuz会根据帖子的热度不同采用不同的缓存策略, 根据用户习惯,而只缓存帖子的第一页(因为很少有人会翻帖子).

于此类似的思想, PHP鼓励8位一下的字符索引, 他以8为单位使用unrolled来提高效率, 这不得不说也是个很细节的,很细致的地方.

另外还有inline, register变量 … 可以看出PHP的开发者在hash的优化上也是煞费苦心

最后就是, hash的初始值设置成了5381, 相比在Apache中的times算法和Perl中的Hash算法(都采用初始hash为0), 为什么选5381呢? 具体的原因我也不知道, 但是我发现了5381的一些特性:

Magic Constant 5381:
1. odd number
2. prime number
3. deficient number

看了这些, 我有理由相信这个初始值的选定能提供更好的分类.
PHP 相关文章推荐
PHP 开源框架22个简单简介
Aug 24 PHP
浅析51个PHP处理字符串的函数
Aug 02 PHP
php使用date和strtotime函数输出指定日期的方法
Nov 14 PHP
dvwa+xampp搭建显示乱码的问题及解决方案
Aug 23 PHP
PHP中addcslashes与stripcslashes函数用法分析
Jan 07 PHP
php单链表实现代码分享
Jul 04 PHP
laravel5创建service provider和facade的方法详解
Jul 26 PHP
php中引用符号(&amp;)的使用详细介绍
Dec 06 PHP
php异步:在php中使用fsockopen curl实现类似异步处理的功能方法
Dec 10 PHP
用PHP将Unicode 转化为UTF-8的实现方法(推荐)
Feb 08 PHP
PHP基于正则批量替换Img中src内容实现获取缩略图的功能示例
Jun 07 PHP
实例分析10个PHP常见安全问题
Jul 09 PHP
php去除字符串换行符示例分享
Feb 13 #PHP
php中url函数介绍及使用示例
Feb 13 #PHP
php中的filesystem文件系统函数介绍及使用示例
Feb 13 #PHP
php实现cc攻击防御和防止快速刷新页面示例
Feb 13 #PHP
php中hashtable实现示例分享
Feb 13 #PHP
php实现下载限制速度示例分享
Feb 13 #PHP
php解压文件代码实现php在线解压
Feb 13 #PHP
You might like
PHP安全配置详细说明
2011/09/26 PHP
『PHP』PHP截断函数mb_substr()使用介绍
2013/04/22 PHP
PHP导出带样式的Excel示例代码
2016/08/28 PHP
PHP+Ajax实现的检测用户名功能简单示例
2019/02/12 PHP
jQuery 表单验证扩展代码(二)
2010/10/20 Javascript
javascript实现图片切换的幻灯片效果源代码
2012/12/12 Javascript
angular.element方法汇总
2015/01/07 Javascript
轮播的简单实现方法
2016/07/28 Javascript
JS实现根据文件字节数返回文件大小的方法
2016/08/02 Javascript
jQuery插件echarts实现的多柱子柱状图效果示例【附demo源码下载】
2017/03/04 Javascript
详解JavaScript对象的深浅复制
2017/03/30 Javascript
js实现分页功能
2017/05/24 Javascript
Vue计算属性的使用
2017/08/04 Javascript
layui.use模块外部使用其内部定义的js封装函数方法
2019/09/16 Javascript
[00:35]DOTA2上海特级锦标赛 Newbee战队宣传片
2016/03/03 DOTA
Python之re操作方法(详解)
2017/06/14 Python
Django查询数据库的性能优化示例代码
2017/09/24 Python
python tensorflow基于cnn实现手写数字识别
2018/01/01 Python
zookeeper python接口实例详解
2018/01/18 Python
浅谈Pandas中map, applymap and apply的区别
2018/04/10 Python
django 微信网页授权认证api的步骤详解
2019/07/30 Python
用python实现英文字母和相应序数转换的方法
2019/09/18 Python
Python zip函数打包元素实例解析
2019/12/11 Python
keras 读取多标签图像数据方式
2020/06/12 Python
Python解析微信dat文件的方法
2020/11/30 Python
html5指南-6.如何创建离线web应用程序实现离线访问
2013/01/07 HTML / CSS
html5 worker 实例(二) 图片变换效果
2013/06/24 HTML / CSS
GOOD AMERICAN官网:为曲线性感而设计
2017/12/28 全球购物
法拉利英国精品店:Ferraris Boutique UK
2019/07/20 全球购物
美国沙龙美发产品购物网站:Hair.com by L’Oreal
2020/11/09 全球购物
工程业务员工作职责
2013/12/07 职场文书
国际金融专业大学生职业生涯规划书
2013/12/28 职场文书
作风转变心得体会
2014/09/02 职场文书
教师个人查摆剖析材料
2014/10/14 职场文书
2014年应急管理工作总结
2014/11/26 职场文书
MYSQL 的10大经典优化案例场景实战
2021/09/14 MySQL