一站式
企业服务平台
132-8122-9158

hash函数与其他函数相比有哪些特点?(用hash函数破解各种复杂的程序)

广告位招租
联系电话:13518188210

一,写于前

现代编程语言通常提供hash表容器,如c++中std:hash_map、golang中map底层均采用hashtable等,究竟是何种魔法使hash_table能在编程上占得一席之地呢,以下将为大家缓缓揭开这一答案

hash表有哪些功能?

在谈论hash表实现时首先要问个问题我们知道,指针有两种:一种叫栈,另一种叫队列。栈和队列都可以用来存储数据,但是它们之间并不完全一样,栈可以存放比较大的文件;而队列只能存小文件对数组的存取可采用索引、array〔0〕,可得到0索引中的数值,取数值的效率为O(1),若对字符串类型若能达到同类存取,则不太完善,先用字符串转数,然后转为array〔1〕取数值,则效率为O(2)

hash函数与其他函数相比有哪些特点?(用hash函数破解各种复杂的程序)

hash表构成

上图神秘的黑魔法是hash功能,那hash功能如此牛气,是不是有问题呢? 其实,我们可以利用hash函数解决很多实际问题。下面我们就来看看如何使用hash函数破解各种复杂的程序吧!一、Hash函数与其他函数相比有哪些特点?1hash函数中存在的最大问题是hash冲突。下图中,在相同槽位上面临着不同字符串的映射

hash函数与其他函数相比有哪些特点?(用hash函数破解各种复杂的程序)

hash的矛盾

工程实际中通常采用挂链,即每一个hashtable内的槽位为链表,发生冲突后即向链表表尾部添加新的节点

hash函数与其他函数相比有哪些特点?(用hash函数破解各种复杂的程序)

化解hash矛盾

三,redis怎样实现一个双hash表

3.1优化冲突挂链效率

在普通hashtable实现上,谈到用挂链表来处理hash冲突图1题,在数据不断增加的情况下,发生冲突的可能性就会不断增加槽位里有大约1000个节点,如果每个节点都进行维护的话,会导致整个系统的效率下降由于冲突是无法避免的,因此当槽位中挂载的节点大于某一比例时,就会扩容出新的hashtable.这种新老并存的情况被确定为rehashing.更大的hashtable能够使冲突槽位中链表长度减小,进而提高效率我个人认为这样做有两点好处:1.增加容量。2.减少内存消耗。但是这两个都不容易做到。我们先来看看为什么会出现上述情况如果这一点可行的话,其背后不过就是一个工程问题

hash函数与其他函数相比有哪些特点?(用hash函数破解各种复杂的程序)

hash迁移图示

3.2扩容流程

上文已经想好了使用双hash表来提高数据扩容后接入效率,那么现在就来讨论一下insert流程吧,接入流程就是先对老hashtable进行接入,再对新hashtable进行接入,去掉同理

注:

其中有一个好处,就是要尽可能地避免rehashing给企业带来冲击,要求平均运行的冲击,每getdeleteset运行一次,就会有部分数据被移植到新的hash表中,这个在redishashtable上就是一个实现

十几个流程图描述如下

hash函数与其他函数相比有哪些特点?(用hash函数破解各种复杂的程序)

扩容流程

3.3收缩流程

收缩流程可由hashtable内完成或对外完成

hashtable通常的实现方式为指针数据如果对于某个hash的table将其存储在100w的元素中然后将其删除

描述:

不支持内部自动收缩(hashtable),通常浪费7.6MB(64位机器)8×10000001×10241×1024.0=7×62890625.此处8为64位机器1指针字节数除以1单位1024为KB除以1为MB为这对大多数人来说已经足够了;但是对于我们这些使用了大容量存储器和处理器的人来说就不是这么简单了,因为它不仅占用大量内存。而且还需要额外的硬盘数据接口

如果仍然极度关心这一点,则可对外调用收缩函数

四,核心代码

下面是golang移值redis双hash表核心编码,供大家参考

typeentry[Kcomparable,Vany]struct{keyKvalVnext*entry[K,V]}typeconfigstruct{hashFuncfunc(strstring)uint64capint}typeHashMap[Kcomparable,Vany]struct{table[2][]*entry[K,V]used[2]uint64sizeExp[2]int8rehashidxintkeySizeintconfigisKeyStrboolinitbool}

func(h*HashMap[K,V])findIndexAndEntry(keyK)(iuint64,e*entry[K,V],errerror){iferr:=h.expand();err!=nil{return0,nil,err}hashCode:=h.calHash(key)idx:=uint64(0)fortable:=0;table2;table++{idx=hashCode&;sizeMask(h.sizeExp[table])head:=h.table[table][idx]forhead!=nil{ifkey==head.key{returnidx,head,nil}head=head.next}if!h.isRehashing(){break}}returnidx,nil,nil}

func(h*HashMap[K,V])Set(kK,vV)error{h.lazyinit()ifh.isRehashing(){h.rehash(1)}index,e,err:=h.findIndexAndEntry(k)iferr!=nil{returnerr}idx:=0ifh.isRehashing(){idx=1}ife!=nil{e.val=vreturnnil}e=&;entry[K,V]{key:k,val:v}e.next=h.table[idx][index]h.table[idx][index]=eh.used[idx]++returnnil}

五,性能压测

以下是性能压测数据

读取速度是标准库的两倍

写入速度比标准库的一次写入速度慢0.018ns

goos:darwingoarch:amd64pkg:github.c_m/guonaihong/gstl/rhashmapcpu:Intel(R)Core(TM)i7-1068NG7CPU@2.30GHzBenchmarkGet-810000000000.4066ns/opBenchmarkGetStd-810000000000.8333ns/opPASSokgithub.c_m/guonaihong/gstl/rhashmap130.007s.比标准库快一倍. goos:darwingoarch:amd64pkg:github.c_m/guonaihong/gstl/rhashmapcpu:Intel(R)Core(TM)i7-1068NG7CPU@2.30GHzBenchmarkSet-810000000000.1690ns/opBenchmarkSetStd-810000000000.1470ns/opPASSokgithub.c_m/guonaihong/gstl/rhashmap3.970s五百万数据的Get操作时间

六,完整代码

如果你还有兴趣了解其他部分,请看以下网址,其中包括Get,Set和Delete的完整实现

赞(7) 联系作者
未经允许不得转载:【聚禄鼎】一站式企业服务平台 » hash函数与其他函数相比有哪些特点?(用hash函数破解各种复杂的程序)

评论 抢沙发

让我们一起创建更加美好的网络世界

本站部分资源来自于网络收集,若侵犯了你的隐私或版权,请及时联系我们删除有关信息!

扫码添加站长微信

扫码添加小编微信

登录

找回密码

注册