zoukankan      html  css  js  c++  java
  • 分享一个简单高效的哈希表C语言实现

    代码路径:https://github.com/prophetss/hashtable

      hashtable是一种非常实用的数据结构,尤其数据量相当大的时候,当然其中很关键的一点是hash算法。之前看redis数据库源码它里面实现hash的算法为murmurhash3,后来发现了这个xxhash。它的hash速度要比前者更快,而且散列效果也同样相当出色,当然此算法也有不足之处:64位hash只在64位程序跑很快,而且代码相比前者代码多,所以我基于此hash算法尝试写了一个hashtable。

      当前代码实现了创建、查找、添加、删除、获取所有元素、重哈希和自定义比较函数。有引用(key拷贝数据value拷贝指针)拷贝(key拷贝数据value拷贝数据)两种模式可选。自动扩缩容,负载均衡(内部存在两张表,不会扩容rehash导致某单次速度过慢)。C/C++、windows和linux通用,需要说明以下几点:

      1. 表起始容量和负载因子默认为hashtable.h内的DEFAULT_CAPACITY和MAX_LOAD_FACTOR(扩容点)、MIN_LOAD_FACTOR(缩容点)宏控制,hash种子默认创建表为time(0)。也可以之后通过htrh接口重新设置

      2. 创建时有拷贝和引用两种方式选择(通过枚举enum {REF_MODE = 0, COPY_MODE}设置),拷贝模式会拷贝key和value数据,引用模式会拷贝key数据和value数据指针(外部value数据改变表内数据也会同时改变)。

      3. 添加有两个接口htset(成功时返回0,如果key值相同会发生覆盖同时返回1)和htsetnx(成功时返回0,如果key值相同不覆盖同时返回-1)。

      4. 获取所有元素也分拷贝和引用两种模式,都返回一个元素指针数组。前者指针指向复制数据,后者指向表内数据。两者都有内部内存申请。

      5. 可以通过ht_set_compare_func设置自定义键值比较方法,默认为memcmp。

      6. 扩容方面我参考了redis哈希表的扩容思想,内部存在两个表,扩容时不会一次将所有数据重新拷贝,而是每次逐元素拷贝,平摊效率以追求更好的负载均衡。

      所有功能都有简单的测试代码,DEBUG模式有单次速度统计和结果校验,性能测试(8起始容量0.75/0.15负载因子)随机选取一百万条16字节key和16字节value分别连续插入、查询、获取所有元素、重哈希和删除(代码都可自由设置,详细请看test_hash.c内代码)。下面是性能测试结果仅供参考(电脑配置i5-3470 3.20 GHz Linux64位):

        

                                     DEBUG模式

                                    RELEASE模式

      上面结果由于随机数据和不同hash种子可能略有波动。打开debug模式(打开test_hash.c内DEBUG宏或make sample_d)会有10%-20%的性能损失。

      然后我这里实现的扩缩容的策略为每次扩大(缩小)一倍,摊还分析插入n个元素时间复杂度应为1+...(n个1)...+1+1+2+4+8...n(假设n是2的幂次方),其和为3n,所以为线性时间,而且由于将每次扩容后元素转移分摊到每次增删查中,因此可以得到更好的负载均衡。

     

    最后我翻译个(谷歌翻译..)xxhash网站说明供大家看下:

      xxHash是一种非常快速的非加密散列算法,其工作速度接近RAM限制。它有两种版本,32位和64位。

      该基准测试使用Austin Appleby的开源SMHasher程序,在Windows 7 32位单线程模式下使用Visual C编译。 参考系统使用Core 2 Duo @ 3.0GHz

    NameSpeedQualityAuthor
    xxHash 5.4 GB/s 10 Y.C.
    MurmurHash 3a 2.7 GB/s 10 Austin Appleby
    SBox 1.4 GB/s 9 Bret Mulvey
    Lookup3 1.2 GB/s 9 Bob Jenkins
    CityHash64 1.05 GB/s 10 Pike & Alakuijala
    FNV 0.55 GB/s 5 Fowler, Noll, Vo
    CRC32 0.43 GB/s 9  
    MD5-32 0.33 GB/s 10 Ronald L.Rivest
    SHA1-32 0.28 GB/s 10

    Q.Score是散列函数质量的度量。 这取决于成功通过SMHasher测试集。 10是一个完美的分数。 分数<5的算法未在此表中列出。

    由于Mathias Westerdahl的贡献,创建了新版本XXH64,该版本为64位系统提供了卓越的速度和分散性。 但请注意,使用32位版本,32位应用程序的运行速度仍将更快。

    在Linux Mint 64位上使用GCC 4.8.2编译的SMHasher速度测试。 参考系统使用Core i5-3340M @ 2.7GHz

    VersionSpeed on 64-bitsSpeed on 32-bits
    XXH64 13.8 GB/s 1.9 GB/s
    XXH32 6.8 GB/s 6.0 GB/s
  • 相关阅读:
    php环境配置中各个模块在网站建设中的功能
    PHP+Apache+MySQL+phpMyAdmin在win7系统下的环境配置
    August 17th 2017 Week 33rd Thursday
    August 16th 2017 Week 33rd Wednesday
    August 15th 2017 Week 33rd Tuesday
    August 14th 2017 Week 33rd Monday
    August 13th 2017 Week 33rd Sunday
    August 12th 2017 Week 32nd Saturday
    August 11th 2017 Week 32nd Friday
    August 10th 2017 Week 32nd Thursday
  • 原文地址:https://www.cnblogs.com/prophet-ss/p/8812265.html
Copyright © 2011-2022 走看看