目录
前言
Jenkins hash
大端小端
rot 宏
mix 宏
final 宏
hash 算法
murmur3 hash
Additive Hash
Rotating Hash
One-at-a-Time Hash
Bernstein hash
Goulburn Hash
Murmur Hash
Pearson Hash
CRC Hashing
Generalized CRC Hashing
Zobrist Hashing
首页 数据库 mysql教程 memcached 源码阅读之 字符串 hash 与 搜集的一些 字符串 hash

memcached 源码阅读之 字符串 hash 与 搜集的一些 字符串 hash

Jun 07, 2016 pm 04:41 PM
hash memcached 字符串 源码 阅读

前言 在 memcached 源码阅读之 hash table文章的最后我说了,要研究一下 memcached 的 字符串 hash 方法的。 现在就开始记录下研究的结果。 Jenkins hash jenkins 的位置在 jenkins_hash.c . 大端小端 Little-Endian就是低位字节排放在内存的低地址端,高位

cover

前言

在 memcached 源码阅读之 hash table文章的最后我说了,要研究一下 memcached 的 字符串 hash 方法的。
现在就开始记录下研究的结果。

Jenkins hash

jenkins 的位置在 jenkins_hash.c .

大端小端

Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:

1)大端模式:  
低地址 -----------------> 高地址  
0x12  |  0x34  |  0x56  |  0x78  
2)小端模式:  
低地址 ------------------> 高地址  
0x78  |  0x56  |  0x34  |  0x12  
登录后复制
#if ENDIAN_BIG == 1
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 1
#else
# if ENDIAN_LITTLE == 1
#  define HASH_LITTLE_ENDIAN 1
#  define HASH_BIG_ENDIAN 0
# else
#  define HASH_LITTLE_ENDIAN 0
#  define HASH_BIG_ENDIAN 0
# endif
#endif
登录后复制

rot 宏

看到的第一个是 rot 宏。
这个宏的作用是循环左移若干位。

#define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k))))
登录后复制

mix 宏

一个可逆的加密。
This is reversible, so any information in (a,b,c) before mix() is still in (a,b,c) after mix().

#define mix(a,b,c) \
{ \
  a -= c;  a ^= rot(c, 4);  c += b; \
  b -= a;  b ^= rot(a, 6);  a += c; \
  c -= b;  c ^= rot(b, 8);  b += a; \
  a -= c;  a ^= rot(c,16);  c += b; \
  b -= a;  b ^= rot(a,19);  a += c; \
  c -= b;  c ^= rot(b, 4);  b += a; \
}
登录后复制

final 宏

final mixing of 3 32-bit values (a,b,c) into c
将 a,b,c 合并到 c中。

#define final(a,b,c) \
{ \
  c ^= b; c -= rot(b,14); \
  a ^= c; a -= rot(c,11); \
  b ^= a; b -= rot(a,25); \
  c ^= b; c -= rot(b,16); \
  a ^= c; a -= rot(c,4);  \
  b ^= a; b -= rot(a,14); \
  c ^= b; c -= rot(b,24); \
}
登录后复制

hash 算法

源代码中大端小端,而且还分是 0x3 还是 0x1,这个目前就不知道干什么了。

uint32_t jenkins_hash( const void *key, size_t length) {
    uint32_t a,b,c;
    a = b = c = 0xdeadbeef + ((uint32_t)length) + 0;
    const char *k = (const char *)key;
    while (length > 12) {
        a += ((uint32_t)k[0])<<24;
        a += ((uint32_t)k[1])<<16;
        a += ((uint32_t)k[2])<<8;
        a += ((uint32_t)k[3]);
        b += ((uint32_t)k[4])<<24;
        b += ((uint32_t)k[5])<<16;
        b += ((uint32_t)k[6])<<8;
        b += ((uint32_t)k[7]);
        c += ((uint32_t)k[8])<<24;
        c += ((uint32_t)k[9])<<16;
        c += ((uint32_t)k[10])<<8;
        c += ((uint32_t)k[11]);
        mix(a,b,c);
        length -= 12;
        k += 12;
    }
    switch(length) {
    case 12:
        c+=k[11];
    case 11:
        c+=((uint32_t)k[10])<<8;
    case 10:
        c+=((uint32_t)k[9])<<16;
    case 9 :
        c+=((uint32_t)k[8])<<24;
    case 8 :
        b+=k[7];
    case 7 :
        b+=((uint32_t)k[6])<<8;
    case 6 :
        b+=((uint32_t)k[5])<<16;
    case 5 :
        b+=((uint32_t)k[4])<<24;
    case 4 :
        a+=k[3];
    case 3 :
        a+=((uint32_t)k[2])<<8;
    case 2 :
        a+=((uint32_t)k[1])<<16;
    case 1 :
        a+=((uint32_t)k[0])<<24;
        break;
    case 0 :
        return c;
    }
    final(a,b,c);
    return c;
}
登录后复制

看完这个代码,我们可以给他缩短一下。

uint32_t jenkins_hash( const void *key, size_t length) {
    uint32_t a,b,c;
    a = b = c = 0xdeadbeef + ((uint32_t)length) + 0;
    const char *k = (const char *)key;
    while (length >= 12) {
        a += *((uint32_t*)(k+0));
        b += *((uint32_t*)(k+4));
        c += *((uint32_t*)(k+8));
        mix(a,b,c);
        length -= 12;
        k += 12;
    }
    if(length == 0) {
        return c;
    }
    switch(length) {
        case 11:
            c+=((uint32_t)k[10])<<8;
        case 10:
            c+=((uint32_t)k[9])<<16;
        case 9 :
            c+=((uint32_t)k[8])<<24;
        case 8 :
            b += *((uint32_t*)(k+4));
            a += *((uint32_t*)(k+0));
            break;
        case 7 :
            b+=((uint32_t)k[6])<<8;
        case 6 :
            b+=((uint32_t)k[5])<<16;
        case 5 :
            b+=((uint32_t)k[4])<<24;
        case 4 :
            a += *((uint32_t*)(k+0));
            break;
        case 3 :
            a+=((uint32_t)k[2])<<8;
        case 2 :
            a+=((uint32_t)k[1])<<16;
        case 1 :
            a+=((uint32_t)k[0])<<24;
    }
    final(a,b,c);
    return c;
}
登录后复制

murmur3 hash

murmur3 hash 的位置在 murmur3_hash.c .

//不检查数据越界问题,主要用于得到一些随机数字
#define    FORCE_INLINE inline __attribute__((always_inline))
//循环左移
static inline uint32_t ROTL32 ( uint32_t x, int8_t r ) {
    return (x << r) | (x >> (32 - r));
}
//得到指针p位置的值,i可能为负数
static FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i ) {
    return p[i];
}
static FORCE_INLINE uint32_t fmix32 ( uint32_t h ) {
    h ^= h >> 16;
    h *= 0x85ebca6b;
    h ^= h >> 13;
    h *= 0xc2b2ae35;
    h ^= h >> 16;
    return h;
}
uint32_t MurmurHash3_x86_32 ( const void * key, size_t length) {
    const uint8_t * data = (const uint8_t*)key;
    const int nblocks = length / 4;
    uint32_t h1 = 0;
    uint32_t c1 = 0xcc9e2d51;
    uint32_t c2 = 0x1b873593;
    const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
    for(int i = -nblocks; i; i++) {
        uint32_t k1 = getblock32(blocks,i);
        k1 *= c1;
        k1 = ROTL32(k1,15);
        k1 *= c2;
        h1 ^= k1;
        h1 = ROTL32(h1,13);
        h1 = h1*5+0xe6546b64;
    }
    const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
    uint32_t k1 = 0;
    switch(length & 3) {
        case 3:
            k1 ^= tail[2] << 16;
        case 2:
            k1 ^= tail[1] << 8;
        case 1:
            k1 ^= tail[0];
            k1 *= c1;
            k1 = ROTL32(k1,15);
            k1 *= c2;
            h1 ^= k1;
    };
    h1 ^= length;
    h1 = fmix32(h1);
    return h1;
}
登录后复制

Additive Hash

ub4 additive(char *key, ub4 len, ub4 prime){
    ub4 hash, i;
    for (hash=len, i=0; i<len; ++i) 
        hash += key[i];
    return (hash % prime);
}
登录后复制

Rotating Hash

ub4 rotating(char *key, ub4 len, ub4 prime){
    ub4 hash, i;
    for (hash=len, i=0; i<len; ++i)
        hash = (hash<<4)^(hash>>28)^key[i];
    return (hash % prime);
}
登录后复制

One-at-a-Time Hash

ub4 one_at_a_time(char *key, ub4 len){
    ub4   hash, i;
    for (hash=0, i=0; i<len; ++i){
        hash += key[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
    hash += (hash << 3);
    hash ^= (hash >> 11);
    hash += (hash << 15);
    return (hash & mask);
}
登录后复制

Bernstein hash

ub4 bernstein(ub1 *key, ub4 len, ub4 level){
    ub4 hash = level;
    ub4 i;
    for (i=0; i<len; ++i) hash = 33*hash + key[i];
    return hash;
}
登录后复制

Goulburn Hash

u4 goulburn( const unsigned char *cp, size_t len, uint32_t last_value){
    register u4 h = last_value;
    int u;
    for( u=0; u<len; ++u ) {
        h += g_table0[ cp[u] ];
        h ^= (h << 3) ^ (h >> 29);
        h += g_table1[ h >> 25 ];
        h ^= (h << 14) ^ (h >> 18);
        h += 1783936964UL;
    }
    return h;
}
登录后复制

Murmur Hash

uint32_t MurmurHash1 ( const void * key, int len, uint32_t seed ){ const unsigned int m = 0xc6a4a793;

const int r = 16;
unsigned int h = seed ^ (len * m);
//----------
const unsigned char * data = (const unsigned char *)key;
while(len >= 4){
    unsigned int k = *(unsigned int *)data;
    h += k;
    h *= m;
    h ^= h >> 16;
    data += 4;
    len -= 4;
}
//----------
switch(len){
    case 3:
    h += data[2] << 16;
    case 2:
    h += data[1] << 8;
    case 1:
    h += data[0];
    h *= m;
    h ^= h >> r;
};
//----------
h *= m;
h ^= h >> 10;
h *= m;
h ^= h >> 17;
return h;
登录后复制

}

Pearson Hash

//This preinitializes tab[] to an arbitrary permutation of 0 .. 255.
char pearson(char *key, ub4 len, char tab[256]){
    char hash;
    ub4  i;
    for (hash=len, i=0; i<len; ++i) 
        hash=tab[hash^key[i]];
    return (hash);
}
登录后复制

CRC Hashing

ub4 crc(char *key, ub4 len, ub4 mask, ub4 tab[256]){
    ub4 hash, i;
    for (hash=len, i=0; i<len; ++i)
        hash = (hash >> 8) ^ tab[(hash & 0xff) ^ key[i]];
    return (hash & mask);
}
登录后复制

Generalized CRC Hashing

//The size of tab[] is the maximum number of input bits. 
//Values in tab[] are chosen at random. 
ub4 universal(char *key, ub4 len, ub4 mask, ub4 tab[MAXBITS]){
    ub4 hash, i;
    for (hash=len, i=0; i<(len<<3); i+=8){
        register char k = key[i>>3];
        if (k&0x01) hash ^= tab[i+0];
        if (k&0x02) hash ^= tab[i+1];
        if (k&0x04) hash ^= tab[i+2];
        if (k&0x08) hash ^= tab[i+3];
        if (k&0x10) hash ^= tab[i+4];
        if (k&0x20) hash ^= tab[i+5];
        if (k&0x40) hash ^= tab[i+6];
        if (k&0x80) hash ^= tab[i+7];
    }
    return (hash & mask);
}
登录后复制

Zobrist Hashing

ub4 zobrist( char *key, ub4 len, ub4 mask, ub4 tab[MAXBYTES][256]){
    ub4 hash, i;
    for (hash=len, i=0; i<len; ++i)
        hash ^= tab[i][key[i]];
    return (hash & mask);
}
登录后复制
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何在沉浸式阅读器中使用Microsoft Reader Coach 如何在沉浸式阅读器中使用Microsoft Reader Coach Mar 09, 2024 am 09:34 AM

在这篇文章中,我们将向你展示如何在WindowsPC上的沉浸式阅读器中使用Microsoft阅读教练。阅读指导功能帮助学生或个人练习阅读并培养他们的识字技能。你从阅读支持的应用程序中的一段或一份文档开始,基于此,你的阅读报告由阅读教练工具生成。阅读报告显示了阅读的准确性、阅读所用的时间、每分钟的正确单词数,以及你在阅读时发现最具挑战性的单词。你还将能够练习这些单词,这总体上有助于培养你的阅读技能。目前,仅有Office或Microsoft365(包括OneNoteforWeb和WordforWe

python怎么重复字符串_python重复字符串教程 python怎么重复字符串_python重复字符串教程 Apr 02, 2024 pm 03:58 PM

1、首先打开pycharm,进入到pycharm主页。2、然后新建python脚本,右键--点击new--点击pythonfile。3、输入一段字符串,代码:s="-"。4、接着需要把字符串里面的符号重复20次,代码:s1=s*20。5、输入打印输出代码,代码:print(s1)。6、最后运行脚本,在最底部会看到我们的返回值:-就重复了20次。

PHP中int类型转字符串的方法详解 PHP中int类型转字符串的方法详解 Mar 26, 2024 am 11:45 AM

PHP中int类型转字符串的方法详解在PHP开发中,经常会遇到将int类型转换为字符串类型的需求。这种转换可以通过多种方式实现,本文将详细介绍几种常用的方法,并附带具体的代码示例来帮助读者更好地理解。一、使用PHP内置函数strval()PHP提供了一个内置函数strval(),可以将不同类型的变量转换为字符串类型。当我们需要将int类型转换为字符串类型时,

Golang字符串是否以指定字符结尾的判断方法 Golang字符串是否以指定字符结尾的判断方法 Mar 12, 2024 pm 04:48 PM

标题:Golang中判断字符串是否以指定字符结尾的方法在Go语言中,有时候我们需要判断一个字符串是否以特定的字符结尾,这在处理字符串时十分常见。本文将介绍如何使用Go语言来实现这一功能,同时提供代码示例供大家参考。首先,让我们来看一下Golang中如何判断一个字符串是否以指定字符结尾的方法。Golang中的字符串可以通过索引来获取其中的字符,而字符串的长度可

Golang中如何检查字符串是否以特定字符开头? Golang中如何检查字符串是否以特定字符开头? Mar 12, 2024 pm 09:42 PM

Golang中如何检查字符串是否以特定字符开头?在使用Golang编程时,经常会遇到需要检查一个字符串是否以特定字符开头的情况。针对这一需求,我们可以使用Golang中的strings包提供的函数来实现。接下来将详细介绍如何使用Golang检查字符串是否以特定字符开头,并附上具体的代码示例。在Golang中,我们可以使用strings包中的HasPrefix

解决PHP中16进制转字符串出现中文乱码的方法 解决PHP中16进制转字符串出现中文乱码的方法 Mar 04, 2024 am 09:36 AM

解决PHP中16进制转字符串出现中文乱码的方法在PHP编程中,有时候我们会遇到需要将16进制表示的字符串转换为正常的中文字符的情况。然而,在进行这个转换的过程中,有时会遇到中文乱码的问题。这篇文章将为您提供解决PHP中16进制转字符串出现中文乱码的方法,并给出具体的代码示例。使用hex2bin()函数进行16进制转换PHP内置的hex2bin()函数可以将1

如何在Go语言中截取字符串 如何在Go语言中截取字符串 Mar 13, 2024 am 08:33 AM

Go语言是一种强大且灵活的编程语言,它提供了丰富的字符串处理功能,包括字符串截取。在Go语言中,我们可以使用切片(slice)来截取字符串。接下来,将详细介绍如何在Go语言中截取字符串,并附上具体的代码示例。一、使用切片截取字符串在Go语言中,可以使用切片表达式来截取字符串的一部分。切片表达式的语法如下:slice:=str[start:end]其中,s

PHP字符串匹配技巧:避免模糊包含表达式 PHP字符串匹配技巧:避免模糊包含表达式 Feb 29, 2024 am 08:06 AM

PHP字符串匹配技巧:避免模糊包含表达式在PHP开发中,字符串匹配是一个常见的任务,通常用于查找特定的文本内容或验证输入的格式。然而,有时候我们需要避免使用模糊的包含表达式来确保匹配的准确性。本文将介绍一些在PHP中进行字符串匹配时避免模糊包含表达式的技巧,并提供具体的代码示例。使用preg_match()函数进行精确匹配在PHP中,可以使用preg_mat

See all articles