第11章闪存数据库实验环境的搭建

Flash-DBSim[SuJXCY09]是由中国科学与技术大学知识与数据工程实验室开发的闪存模拟器,它为各种算法性能验证提供了仿真环境,可以模拟闪存技术研究中出现的各种实验环境。该模拟器可以根据上层应用的需要模拟出不同特性的固态盘,如闪存的读写代价不一致和写前擦除等特性。Flash-DBSim使用的程序设计语言为c++,开发工具为visualstudio2008。很多已有的研究(比如缓冲区替换算法CCF-LRU和AD-LRU)都采用了该模拟器进行算法性能的比较。

Flash-DBSim具有如下特点:

闪存存储系统包括两个关键组件,即闪存技术设备模块MTD和闪存转换层FTL。MTD(MemoryTechnologyDriver)提供了对闪存的读、写和擦除操作的函数,它直接控制物理闪存芯片。FTL(FlashTranslationLayer)是架构在MTD层之上的,用来实现地址翻译、空间分配和垃圾回收等操作,从而把一个闪存设备模拟成一个块设备,使得文件系统和用户应用可以像访问磁盘一样访问闪存设备。

图[Flash-DBsim-two-ways]显示了实现一个闪存存储系统的两种不同方式。第一种方式是,MTD和FTL被封装在闪存设备(比如固态盘)中,如图[Flash-DBsim-two-ways](a)所示。第二种方式是,MTD和FTL在闪存设备上面的软件系统中实现,如图[Flash-DBsim-two-ways](b)所示。Flash-DBSim采用了第一种实现方式,即封装在一个闪存设备中,只不过在Flash-DBSim中,这个闪存设备并非真实的设备,而是一个虚拟的设备。

图[Flash-DBsim-two-ways]闪存存储系统的两种实现方式

图[Flash-DBsim-architecture]给出了Flash-DBSim的体系架构,包括以下几个组件:

公共访问接口:该组件是开放给所有用户的,它对用户隐藏了所有底层细节。

图[Flash-DBsim-architecture]Flash-DBSim的体系架构

Flash-DBSim官方网站提供了两个不同版本的Flash-DBSim下载内容:

Flash-DBSim使用的程序设计语言为c++,开发工具为visualstudio2008,因此,读者对压缩文件flash-dbsim-source-1.6.zip进行解压后,可以得到名为“flash-dbsim-source-1.6”的文件夹,该文件夹下面包含一个解决方案文件和两个工程文件夹:

这部分内容首先简单介绍FlashDBSimDll_Sample工程中各个文件的作用,然后介绍如何设置模拟器的参数,接下来给出了一个实例来演示如何测试LRU算法的性能,最后,简单介绍如何测试自己的缓冲区替换算法性能。

从Flash-DBSim官方网站下载得到原始压缩文件“flash-dbsim-source-1.6.zip”以后,解压缩得到名为“flash-dbsim-source-1.6”的文件夹,该文件夹下面包含一个解决方案文件FlashDBSimDll.sln和两个工程文件夹。

在FlashDBSimDll_Sample工程下面,包含4个头文件、3个C++源文件和2个测试数据集文件:

打开工程FlashDBSimDll_Sample下的main.cpp文件,可以直接运行程序。下面介绍各个文件的作用:

Flash-DBSim是一种高效的、可重用和可配置的闪存存储系统仿真平台,可以根据上层应用的需要模拟出不同的特性的固态盘,从而可以方便地为上层应用提供仿真测试环境。Flash-DBSim闪存模拟器通常可以采用下面表[Flash-DBSim-parameters]中的典型参数配置:

表[Flash-DBSim-parameters].NAND闪存的特性参数

Flash-DBSim中的闪存基本参数设置是在FlashDBSimDll_Sample工程下面的main.cpp文件中完成的,相应的代码如下:

vfdInfo.pageCountPerBlock=64;//设置每个块中包含的页的数量

vfdInfo.pageSize.size1=2048;//设置页的数据区域的大小

vfdInfo.pageSize.size2=0;//设置页的带外数据区域的大小

vfdInfo.eraseLimitation=100000;//设置闪存的每个块的擦除次数上限

vfdInfo.readTime.randomTime=25;//设置随机读操作延迟为25微秒

vfdInfo.readTime.serialTime=0;//设置顺序读操作延迟为0微秒

vfdInfo.programTime=200;//设置写操作延迟为200微秒

vfdInfo.eraseTime=1500;//设置擦除操作延迟为1500微秒

这些闪存特性参数可以根据具体的实验要求而有所不同,可以在main.cpp文件中进行修改。需要指出的是,如果实验中需要修改缓冲区的大小,可以在BufferAlgorithm.h文件中修改变量DEFBUFSIZE的值,该值默认为1536,即缓冲区可以容纳1536个页,每个页大小为2048字节,因此,缓冲区大小为3MB。。

FlashDBSimDll_Sample工程提供了一个测试LRU(LeastRecentlyUsed)算法性能实验的例子。为了更好地设计实现自己的缓冲区替换算法,读者应该首先了解LRU算法性能测试的基本步骤、所使用的数据结构和算法成员函数。

在FlashDBSimDll_Sample工程中,通过main.cpp来调用各种缓冲区替换算法,测试任何缓冲区替换算法(包括LRU算法和自己设计的算法)的性能时,都需要严格遵循以下5个步骤:

在Flash-DBSim自带的实例工程FlashDBSimDll_Sample中,包含一个头文件LRU.h,这个头文件里定义了两个结构体LRUBCB和LRUElement,以及一个数组ftop,它们都是为LRU算法服务的。如图[Flash-DBSim-LRU]所示,LRU算法使用的数据结构包含了一个LRU链表、一个哈希表(ptop)和一个数组(ftop),具体作用如下:

当需要读取一个逻辑页时,需要判断该页是否在缓冲区中,方法很简单,只需要根据页号page_id得到哈希值,然后在哈希表ptop找到对应的哈希桶,每个哈希桶都存储了一个链表,如果该链表中不存在与page_id对应的元素,则说明该页不在缓冲区中。如果链表中存在一个与page_id对应的元素,则读取出该元素的frame_id属性的值,到相应的缓冲区单元中读取数据页。

当需要把一个页号为page_id的逻辑页写入缓冲区的帧号为frame_id的某个帧时,首先,修改数组内容,把数组元素ftop[frame_id]的内容设置为page_id,然后,需要根据页号page_id得到哈希值,在哈希表ptop找到对应的哈希桶,每个哈希桶都存储了一个链表,为page_id和frame_id创建一个新的元素加入到链表中。

当需要把一个逻辑页驱逐出缓冲区时,只需要根据页号page_id得到哈希值,然后在哈希表ptop找到对应的哈希桶,每个哈希桶都存储了一个链表,在链表中找到与page_id对应的元素,读取frame_id的值,然后,把内存中帧号为frame_id的缓冲区单元的内容清空。

图[Flash-DBSim-LRU]Flash-DBSim中LRU算法使用的数据结构

下面分别介绍LRU算法的成员函数及其作用。

Public成员函数:

Public:LRU()//构造函数,初始化数据

~LRU()//析构函数,释放资源

voidInit()//初始化,在LRU算法性能测试的基本步骤的第2步与第3步之间调用

intFixPage(intpage_id)//安插一个数据页

NewPageFixNewPage(LBAlba)//安插一个新的数据页

intUnFixPage(intpage_id)//基本不会用到

voidReadFrame(intframe_id,char*buffer)//读一帧数据,用不到

voidWriteFrame(intframe_id,constchar*buffer)//写一帧数据,用不到

intWriteDirty(void)//将内存中的脏页写回闪存

doubleHitRatio(void)//返回命中率

voidRWInfo()//返回读写统计信息

intIsLBAValid(LBAlba)//判断LBA是否有效

intLBAToPID(LBAlba)//通过LBA获取PID

Private成员函数:

inthash(intpage_id)//哈希函数

LRUBCB*PageToLRUBCB(intpage_id)//通过page_id获取块数据

voidRemoveLRUBCB(LRUBCB*pb)//移除块数据

voidInsertLRUEle(intframe_id)//在链表中插入元素

voidRemoveLRUEle(intframe_id)//移除链表元素

voidAdjustLRUList(intframe_id)//调整链表元素(缓冲区命中以后调整命中页在链表中的位置)

voidSetDirty(intframe_id)//设置frame_id的脏标识

intSelectVictim()//选择替换页,缓存替换算法的核心函数

voidRegistEntry(LBAlba,PIDpage_id)//注册一页,用不到

Private成员变量:

intftop[DEFBUFSIZE]//数组

LRUBC*ptop[DEFBUFSIZE]//哈希表

bFramebuf[DEFBUFSIZE]//存放帧数据,用不到

Map//maplist逻辑页号与物理页号的映射关系

LRUElement*lru//链表的表尾指针

LRUElement*mru//链表的表头指针

inthit//命中次数

inttotal//读写操作的次数

intflashreadcount//物理读操作次数

intflashwritecount//物理写操作次数

假设读者需要开展实验测试自己的缓冲区替换算法的性能,建议首先阅读FlashDBSimDll_Sample工程下面的main.cpp、LRU.h和LRU.cpp文件,理解程序运行过程,从而更好地了解Flash-DBSim的使用方法以及如何在main.cpp中调用自己设计实现的其他缓冲区替换算法。在实现自己的缓冲区替换算法时,建议直接在LRU算法基础之上进行修改,这样可以避免引入未知错误。建议深刻理解LRU算法实例的运行细节,这样才能更好地设计实现自己的算法,知道哪些成员函数需要修改,哪些成员函数不需要修改。在实现自己的算法中,可以拷贝LRU算法的代码,修改关键的几个成员函数。这里需要注意的是,由于大部分成员函数不需要修改,如果读者需要实现多个不同的缓冲区替换算法,建议将那些不需要修改的成员函数移到基类BMgr中去。

利用闪存模拟器提供的仿真环境进行实验具有一定的局限性,因此,对于某些闪存研究实验,需要在真实的数据库和闪存设备环境下进行,因此,这里将介绍如何修改PostgreSQL开源数据库的源代码,从而实现真实环境下的性能测试。

在使用PostgreSQL开展实验之前,读者可能会思考一些问题,因此,这里以问答的形式帮助读者对实验的开展有一个整体的认识。

答1:是的,在postgresql-7.3.40/src/backend/storage/buffer目录下修改缓冲区替换算法,修改完成以后还和以前一样安装即可。

问2:要实现多个缓冲区替换算法,是否需要多次安装、卸载PostgreSQL?

答2:是的,一个系统中只有一个PostgreSQL数据库,如果要比较多个缓冲区替换算法的性能,则需要在每次实现一个算法的时候,都分别安装PostgreSQL,获取测试数据,然后卸载PostgreSQL,然后,再去实现下一个算法。

问3:如何将数据存储到固态盘?

问4:实验的输入数据是什么?从哪里来?

答4:开展实验时,不需要我们自己获取输入数据,有一个名为BenchmarkSQL的测试工具,会自动帮我们创建表,创建索引,添加数据。

问6:如何设置缓冲区大小?

答6:在PostgreSQL的源码中,有一个名为NBuffer的变量,默认值是1000,表示有几个缓冲区(数据页),修改缓冲区大小,只需要修改这个变量的值即可。

问7:如何统计写操作次数和命中率?

使用PostgreSQL开展缓冲区替换算法,包括以下4个大的步骤:

第1步:下载PostgreSQL,修改PostgreSQL自带的缓冲区替换算法(LRU算法)的源代码,实现自己的缓冲区替换算法;

第2步:用源码安装的方式把PostgreSQL数据库安装到固态盘;

第3步:安装BenchmarkSQL;

第4步:使用BenchmarkSQL进行性能测试,获取测试结果

以上每一步都可以分为很多小步,其中,第1步最复杂,需要读者首先阅读PostgreSQL源码,在此基础上实现自己的缓冲区替换算法。

接下来的内容,将介绍以下几个方面的细节:

PostgreSQL需要在Linux环境下运行,可以采用虚拟机软件VMware,在其中安装ubuntu系统。

在Linux下安装PostgreSQL,需要遵循Linux下安装源码文件的三个步骤:

(1)./configure

(2)Make

(3)Makeinstall

通过上述三个步骤,就可以把PostgreSQL安装到prefix指定的目录下。

实际上,读者也可以根据PostgreSQL的安装说明文件来指导自己的安装过程。在刚才解压缩得到的postgresql-7.4.30目录下,有一个安装说明文件INSTALL,这里对该说明文件中的几行关键代码做简要解释,具体如下:

./configure#配置

gmake#make

su#切换到root用户

gmakeinstall#安装,以上几步是linux下安装软件的典型方式

adduserpostgres#添加一个用户,添加完用户以后需要通过passwdpostgres来修改该用户的密码

mkdir/usr/local/pgsql/data#新建一个目录,以后数据库的所有数据和操作都在该目录下

chownpostgres/usr/local/pgsql/data#更改目录的所有者为postgres

/usr/local/pgsql/bin/initdb-D/usr/local/pgsql/data#初始化工作区

/usr/local/pgsql/bin/postmaster-D/usr/local/pgsql/data>logfile2>&1&

/usr/local/pgsql/bin/createdbtest#启动服务,并新建一个名为test的数据库

/usr/local/pgsql/bin/psqltest#启动数据库

下面介绍如何将PostgreSQL安装到固态盘,以及如何配置PostgreSQL,使得BenchmarkSQL能够顺利完成对PostgreSQL的性能测试。

把PostgreSQL安装到固态盘,可以执行以下三个步骤:

make

sudomakeinstall

执行完上面3条语句以后,数据库就安装完成了,但是,还有很多工作要做。

其次,在替换完成以后,需要初始化工作区:

mkdir/usr/local/pgsql/data

chownuserName/usr/local/pgsql/data

再次,在初始化工作区以后,需要修改配置文件。进入存储空间所在文件夹(/usr/local/pgsql/data),打开postgresql.conf文件,将#tcpip_socket=false的“#”删除,并把false改为true,另外,需要将#port=5432的“#”删除。

上面步骤完成以后,配置工作就完成了,下面只需要启动数据库服务,然后新建数据库就可以了。

#启动服务

/usr/local/pgsql/bin/pg_ctl-D/usr/local/pgsql/data-llogfilestart

#创建一个名为test的数据库

/usr/local/pgsql/bin/createdbtest

到这里为止,我们的数据库就创建完成了,下面就可以使用BenchmarkSQL来测试性能。

BenchmarkSQL是一款采用TPC-C的、开源的数据库测试工具,几乎不用修改就能测试当前主流数据库的性能。这里介绍BenchmarkSQL的下载、安装和使用方法。

首先,需要修改“BenchmarkSQL-2.3.2/run/”目录下面的postgres.properties文件,设置正确的数据库名和密码。如果之前已经创建了一个名为test的数据库,那么,这里只需要给出相应的账户和密码就可以了,具体配置如下:

driver=org.postgresql.Driver

conn=jdbc:postgresql://localhost:5432/test

user=lalor

password=123456

然后,在“BenchmarkSQL-2.3.2/run/”目录下运行如下命令:

./runSQL.shpostgres.propertiessqlTableCreates

上面的命令用于创建我们进行TPC-C测试所需的数据库表。

./loadData.shpostgres.propertiesnumWarehouses10

上面的命令用于加载我们进行TPC-C测试所需的数据,numWarehouses后的数字可以自行设置。

./runSQL.shpostgres.propertiessqlIndexCreates

上面的命令用于创建我们进行TPC-C测试所需的索引。

./runBenchmark.shpostgres.properties

使用BenchmarkSQL可以帮我们生成测试结果数据,从而了解数据库的性能,但是,如果要获取底层的详细信息,如缓冲区命中率、物理读操作次数和物理写操作次数等,则还需要查看PostgreSQL源代码,通过修改源代码来获取这些信息。具体方法如下:

vimPostgreSQL-7.4.30/src/backend/libpq/pqcomm.c

注册回调函数具体过程包含以下三个步骤:

第2步:定义回调函数

第3步:在合适的地方(pg_init)注册回调函数

voidpq_init(void){PqSendPointer=PqRecvPointer=PqRecvLength=0;PqCommBusy=false;DoingCopyOut=false;on_proc_exit(printBufferUsageInfo,0);//新增加的回调函数注册语句on_proc_exit(pq_close,0);}

通过前面内容的描述,我们已经了解了在PostgreSQL下测试缓冲区替换算法LRU的性能的基本过程。在实际研究工作中,我们需要测试其他多个缓冲区替换算法的性能,从而进行性能比较,但是,一个系统中只能有一个PostgreSQL数据库,在测试完LRU算法的性能以后,我们只能删除PostgreSQL数据库,再吧PostgreSQL数据库中的缓冲区替换算法修改成其他算法,再次进行安装测试。

删除PostgreSQL数据库包括以下4个步骤:

第1步:关闭数据库服务

/usr/local/pgsql/bin/pg_ctl-D/usr/local/pgsql/data-llogfilestop

第2步:删除数据库

/usr/local/pgsql/bin/dropdbtest

第3步:卸载PostgreSQL

sudomakeuninstall

sudomakeclean

第4步:删除目录

sudorm-rf/usr/local/pgsql

下面首先介绍修改PostgreSQL的预备知识,然后介绍修改PostgreSQL缓冲区替换算法的基本步骤,最后给出一个实例,介绍如何修改PostgreSQL实现缓冲区替换算法CFLRU。

图[PostgreSQL-LRU]PostgreSQL中的LRU算法所使用的数据结构

图[PostgreSQL-LRU]显示了PostgreSQL中的LRU算法所使用的“LRU链表”,不过需要注意的是,这个LRU链表并不是真正的链表,而是用数组来实现的,数组名为BufferDescriptors,数组中有NBuffer+1个“描述子”,所谓“描述子”就是一个结构体(BufferDesc)类型的变量,用于表示LRU链表的一个元素,结构体(BufferDesc)类型定义位于头文件buf_internals.h中。如果我们实现的算法中需要增加新的属性,就在该结构体中添加。数组BufferDescriptors中,前NBuffer个元素用来表示空闲缓冲区(数据页),最后一个元素是“哨兵”,设置这个元素是为了方便操作,有一个指针变量SharedFreeList会一直指向“哨兵”位置,当满足SharedFreeList->freeNext==Free_List_Descriptor的时候,就说明缓冲区中的所有数据页都在被使用。有了SharedFreeList,我们就可以很快地从LRU链表中选择LRU位置的数据页作为驱逐页,并将新的数据页插入到LRU链表的MRU位置。

在PostgreSQL中,有了上面的数据结构,实现LRU算法只用到了两个函数:

修改PostgreSQL的缓冲区替换算法主要包括两个步骤:

第1步:修改描述子,增加新属性。若新算法为缓冲区赋予了新的属性,则需要修改PostgreSQL缓冲区描述子的数据结构,在其中定义新的参数,以描述缓冲区的新属性。

第2步:增加新的数据结构和操作。LRU算法要求缓冲池是一个LRU链表,若新算法要求缓冲池是另一种数据结构,就需要对缓冲区管理部分进行相应的修改。首先,需要修改缓冲区描述子的数据结构,增加新的数据结构,满足缓冲池的构建要求;然后,需要修改缓冲池的初始化操作,在初始化时构建新结构的缓冲池;最后,通过修改原有的缓冲池维护操作,或者替换和增加新的维护操作,保证缓冲池的数据结构始终满足新算法的要求。

CFLRU算法[ParkJKKL06]采用了“双区域”机制,把LRU链表划分成两个区域,即工作区域和干净优先区域,两个区域可以采用各种成熟的替换算法(比如LRU)。CFLRU算法不需要增加新属性,只需要判断干净页优先区域(Clean-FirstRegion)中是否有干净页,如果有干净页,就替换干净页,如果没有干净页,就替换LRU位置的数据页。在CFLRU算法中,我们只需要增加一个变量nWindowSize表示干净页优先区域的大小,然后修改GetFreeBuffer()函数即可。

(1)PostgreSQL自带的LRU算法中的GetFreeBuffer()函数

/*

*/

BufferDesc*

GetFreeBuffer(void)

{

BufferDesc*buf;

if(Free_List_Descriptor==SharedFreeList->freeNext)

/*queueisempty.Allbuffersinthebufferpoolarepinned.*/

ereport(ERROR,

(errcode(ERRCODE_INSUFFICIENT_RESOURCES),

returnNULL;

}

buf=&(BufferDescriptors[SharedFreeList->freeNext]);

/*removefromfreelistqueue*/

BufferDescriptors[buf->freeNext].freePrev=buf->freePrev;

BufferDescriptors[buf->freePrev].freeNext=buf->freeNext;

buf->freeNext=buf->freePrev=INVALID_DESCRIPTOR;

buf->flags&=~(BM_FREE);

returnbuf;

(2)采用CFLRU算法时修改以后的GetFreeBuffer()函数

intn=0;

/*selectareplacepageinclean-firstregion*/

while(n

/*Isbufferdirty*/

if(buf->flags&BM_DIRTY||buf->cntxDirty)

buf=&(BufferDescriptors[buf->freeNext]);

/*nomorebuffer*/

if(buf==SharedFreeList)

buf=NULL;

break;

else

{/*selectthispageasreplacepage*/

n++;

*1.buf==NULL说明缓冲区中总共也没有nWindowSize个freebuffer

*2.n>=nWindowSize说明缓冲区中干净页优先区域中,全都是脏页

THE END
1.几种经典的Hash算法的实现源代码(4页)几种经典的算法的实现源代码年月日星期一哈希算法将任意长度的二进制值映射为固定长度的较小二进制值这个小的二进制值称为哈希值哈希值是一段数据唯一且极其紧凑的数值表示形式如果散列一段明文而且哪怕只更改该段落的一个字母随后的哈希都将产生不同的值要找到散列为同一个值的两个不同的输入在计算上是不可能的https://max.book118.com/html/2019/0515/6054020204002031.shtm
2.《一切皆是映射:代码的本质》哈希算法(Hash)哈希表是一个在时间和空间上做出权衡的经典例子。如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);如果没有时间限制,那么我们可以使用无序数组并进行顺序查找,这样只需要很少的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只需要调整哈希函数算法即可在时间和https://www.jianshu.com/p/fa57d21b9ad7
3.PHP实现sha256哈希算法实例代码php技巧哈希 又称作 “散列”,它接收任何一组任意长度的输入信息,通过 哈希 算法变换成固定长度的数据指纹,该指纹就是 哈希值。总体而言,哈希 可理解为一种消息摘要。在PHP 中有这个函数 hash(),可以计算字符串的哈希值,出于好奇我 Google 了一下哈希计算的具体步骤,并使用 PHP 编写了一套计算 sha-256 哈希值的代码https://www.jb51.net/article/272643.htm
4.哈希算法sha哈希算法sha-256的c++源代码Co**il 上传4.01 KB 文件格式 cpp 哈希 sha c++ 源代码 只适用于学习 // 使用平台: 80x86 // 语言: c/c++ // 具体流程请参考wiki百科 http://zh.wikipedia.org/wiki/SHA%E5%AE%B6%E6%97%8F点赞(0) 踩踩(0) 反馈 所需:3 积分 电信网络下载 https://www.coder100.com/index/index/content/id/1061340
5.C语言实现哈希集合算法附完整源代码C/C++C语言实现哈希集合算法-附完整源代码 哈希集合(hashset)是一种非线性容器,常常用于存储键值对。在哈希集合中,数据的存放位置不固定,而且数据不可重复,能够实现高效的增删改查操作。 本文将介绍如何使用C语言实现一个基于哈希算法的集合。我们将演示如何定义哈希函数、创建哈希表以及实现哈希集合的增删改查操作。 https://download.csdn.net/blog/column/12410832/132572503
6.哈希算法sha256的c++源代码哈希算法sha-1 的c++源代码 学习使用 // 使用平台: 80x86 // 语言: c/c++ // 具体流程请参考wiki百科 http://zh.wikipedia.org/wiki/SHA%E5%AE%B6%E6%97%8F 上传者:skywalker_sun时间:2011-07-03 Algorithm-sha-2.zip Algorithm-sha-2.zip,sha-2算法实现,算法是为计算机程序高效、彻底地完成任务而https://www.iteye.com/resource/skywalker_sun-3413764
7.常见的hash算法介绍学亮编程手记的技术博客这些是仅列举的一些常见的哈希算法,每种算法都有其特定的应用场景和性能特性。在选择哈希算法时,需要根据具体的需求和安全要求进行权衡和选择。 SHA-256 java代码示例 下面是一个使用 Java 的 MessageDigest 类实现 SHA-256 哈希算法的示例代码: import java.nio.charset.StandardCharsets; https://blog.51cto.com/zhangxueliang/6406301
8.Awesome第二,朴素字符串匹配算法思想简单,代码实现也非常简单。2. RK算法? Rabin-Karp 算法,属于BF算法的升级版。? RK 算法的思路是这样的:我们通过哈希算法对主串中的 n-m+1 个子串分别求哈希值,然后逐个与模式串的哈希值比较大小。如果某个子串的哈希值与模式串相等,那就说明对应的子https://github.com/Ty-Chen/Awesome-Backend/blob/5ad253a0f2e82d9b83892a60e01a1e0a855d70b3/Data%20Structure%20and%20Algorithm.md
9.shazam音乐检索算法附完整c代码腾讯云开发者社区整个算法非常简单, 最核心的点是 切分5个频段, 用上了时序信息去算哈希。 对于有时序的数据,肯定要用上时序性维度,不然是有失偏颇的。 之余图片,就要用空间性维度,之余视频,时间和空间都要有。 这个算法简单粗暴,也有效。 严格意义上讲,这个算法的泛化能力有待商榷。 https://cloud.tencent.com/developer/article/1179981
10.算法的乐趣如果随着算法演化,有新的动作需要处理,则只需要在函数表中添加新的条目即可,状态转换的代码不需要做任何改动。 算法需要确定性,分支和跳转看似使得算法具有不确定性,但是实际上,分支的判断和选择都是在所有已确定处理流程的框架中进行的,也就是说,这些选择都是算法确定范围之内的选择,对算法确定性没有影响。虽然分支https://www.ituring.com.cn/book/tupubarticle/5656
11.密码学一文读懂MurMurHash2原始代码 先贴一下原汁原味的代码。 32位哈希算法 #include <iostream>//---// MurmurHash2, by Austin Appleby// Note - This code makes a few assumptions about how your machine behaves -// 1. We can read a 4-byte value from any address without crashing// 2. sizeof(int) == 4// https://developer.aliyun.com/article/952944
12.HMAC类(System.Security.Cryptography)MicrosoftLearn基于哈希的消息身份验证代码 (HMAC) 可用于确定通过不安全通道发送的消息是否已被篡改,前提是发送方和接收方共享密钥。 发送方计算原始数据的哈希值,并将原始数据和 HMAC 作为单个消息发送。 接收方重新计算收到的消息上的哈希值,并检查计算的哈希值是否与传输的哈希值匹配。 https://msdn.microsoft.com/zh-cn/library/system.security.cryptography.hmac.aspx