Memcached源码分析(二)-jenkins hash函数

本文探讨了Memcached中可配置的hash算法,重点分析了默认的Jenkins哈希算法。通过观察源码,我们注意到该算法对字符串首地址的特殊处理,以提升处理效率。虽然大端序和小端序部分处理类似,但在文中并未详述。
摘要由CSDN通过智能技术生成

通过启动时的-o hash_algorithm可以配置memcached的hash算法,支持两种算法:jenkins, murmur3,默认是jenkins。
hash源码里面有几点比较有意思,直接在代码里标明。
大端序部分与小端序部分基本一致,就不再标明。
jenkins_hash.c

#if HASH_LITTLE_ENDIAN == 1
uint32_t jenkins_hash(
  const void *key,       /* the key to hash */
  size_t      length)    /* length of the key */
{
  // 由于a,b,c都是4byte的,因此下面每次循环最大处理12byte
  uint32_t a,b,c;                                          /* internal state */
  // union里面有个const变量,不用马上初始化,通过i直接操作,免除了数据强转
  union { const void *ptr; size_t i; } u;     /* needed for Mac Powerbook G4 */

  /* Set up the internal state */
  // 0xdeadbeef是一个魔术数,标记软件崩溃或死锁,但这里好像并没有特别的意义,反汇编的时候方便查找?后面+0似乎也没有意义,知道的博友还望告知一下,不胜感激!
  a = b = c = 0xdeadbeef + ((uint32_t)length) + 0;

  u.ptr = key;
  // 此处的HASH_LITTLE_ENDIAN是多余的,其值必然为1。u.i&0x3是检查地址低两位是否是00,如果是的话可以认为是4字节内存对齐的,可以一次处理4byte。
  if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
    const uint32_t *k = key;                           /* read 32-bit chunks */
#ifdef VALGRIND
    const uint8_t  *k8;
#endif /* ifdef VALGRIND */

    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
    while (length > 12)
    {
      a += k[0];
      b += k[1];
      c += k[2];
      mix(a,b,c);
      length -= 12;
      k += 3;
    }

    /*----------------------------- handle the last (probably partial) block */
    /*
     * "k[2]&0xffffff" actually reads beyond the end of the string, but
     * then masks off the part it's not allowed to read.  Because the
     * string is aligned, the masked-off tail is in the same word as the
     * rest of the string.  Every machine with memory protection I've seen
     * does it on word boundaries, so is OK with this.  But VALGRIND will
     * still catch it and complain.  The masking trick does make the hash
     * noticably faster for short strings (like English words).
     */
#ifndef VALGRIND

    switch(length)
    {
    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
    case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
    case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
    case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
    case 8 : b+=k[1]; a+=k[0]; break;
    case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
    case 6 : b+=k[1]&0xffff; a+=k[0]; break;
    case 5 : b+=k[1]&0xff; a+=k[0]; break;
    case 4 : a+=k[0]; break;
    case 3 : a+=k[0]&0xffffff; break;
    case 2 : a+=k[0]&0xffff; break;
    case 1 : a+=k[0]&0xff; break;
    case 0 : return c;  /* zero length strings require no mixing */
    }

#else /* make valgrind happy */

    k8 = (
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值