1.本发明涉及计算机技术领域,尤其涉及一种基于远程直接内存访问的内存管理方法和设备。
背景技术:
2.远程直接内存访问(remote direct memory access,简称rdma),是为了解决网络传输中服务器端数据处理的延迟而产生的。rdma通过网络把资料直接传入计算机的存储区,将数据从一个系统快速移动到远程系统存储器中,而不对操作系统造成任何影响,这样就不需要用到多少计算机的处理功能。它消除了外部存储器复制和上下文切换的开销,因而能够解放内存带宽和cpu周期用于改进应用系统的性能。
3.现有的远程直接内存访问的内存管理方法,在从计算机系统获得一段内存区域后,是通过ibverbs mr的注册函数ibv_reg_mr将内存区域的地址注册到rdma设备;然后将注册过的内存区域分割成特定大小的内存块,并将分割得到的内存块放入队列中;当有网络传输需求时,从队列中分配内存块。其中可以将内存区域分割成多个不同的大小的内存块,也可以将内存区域分割成全部相同大小的内存块。
4.然而,现有的远程直接内存访问的内存管理方法在实际使用过程中存在着以下问题:
5.1、当出现队列中的内存块不足时,会触发一次系统内存分配与mr注册,由于mr注册操作属于系统调用,速度慢成本高,在内存分配频繁时频繁触发mr注册,会影响远程直接内存访问的性能;
6.2、未考虑多线程下的性能要求,即使对每个队列正确的做了锁,在多个线程同时进行内存的分配和释放时,远程直接内存访问的性能压力仍较大。
技术实现要素:
7.本发明提供一种基于远程直接内存访问的内存管理方法和设备,用以解决现有技术中远程直接内存访问频繁触发mr注册和多线程并发,对远程直接内存访问的性能带来的影响,可以减少对mr注册的触发,使内存分配和释放的所有操作基本都是通过单线程实现,保证远程直接内存访问的性能。
8.第一方面,本发明提供一种基于远程直接内存访问的内存管理方法,包括:
9.向计算机系统申请内存区域,获得所述计算机系统分配的内存区域的地址,并将所获得的内存区域的地址注册到所述计算机系统的rdma设备中;
10.基于所获得的内存区域的地址,按照8mib将所述内存区域划分为内存段,并将每个所述内存段划分为头部和可用内存部,在所述头部设置链表指针,将划分得到的内存段连接成全局堆链表;
11.响应于远程直接内存访问的线程启动,从所述全局堆链表中为所述线程分配内存段,并在所分配的内存段的所述头部设置链表指针,将所分配的内存段连接成线程堆链表,
将所述线程堆链表的头指针返回给所述线程;
12.响应于所述线程接收到内存块分配请求,将所述线程堆链表中的一个内存段划分为四个2mib的子段,并基于请求分配的内存块的大小,将划分得到的一个子段作为一个2mib的大页或者划分为八个256kib的小页;
13.基于与请求分配的内存块的大小相匹配的预先设定的内存分配类型,将所述大页或者一个所述小页划分为大小相同的内存块,选取一个所述内存块作为目标内存块,将所述目标内存块的地址返回给所述线程。
14.根据本发明提供的一种基于远程直接内存访问的内存管理方法,还包括:
15.针对每一线程堆链表,将所划分的内存块的大小相同的页面,基于内存块的使用情况分别连接成页面空闲链表和页面使用链表,形成页面链表组;其中,所述页面为所述大页或者所述小页;
16.响应于所述线程接收到内存块分配请求,基于预先设定的内存分配类型,确定与请求分配的内存块的大小相匹配的内存分配类型;
17.基于所确定的内存分配类型,查询所述页面链表组中对应的页面空闲链表;
18.判断对应的页面空闲链表中是否存在空闲的内存块;
19.若对应的页面空闲链表中存在空闲的内存块,从对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块,将所述目标内存块的地址返回给所述线程;
20.若对应的页面空闲链表中不存在空闲的内存块,将对应的页面空闲链表中的页面连接到对应的页面使用链表中。
21.根据本发明提供的一种基于远程直接内存访问的内存管理方法,还包括:
22.针对每一线程堆链表,将所述线程堆链表中未划分为内存块的大页连接成空闲大页链表,将所述线程堆链表中未划分为内存块的小页连接成空闲小页链表;
23.判断对应的页面空闲链表是否为空;
24.若对应的页面空闲链表非空,判断对应的页面空闲链表中是否存在空闲的内存块;
25.若对应的页面空闲链表为空,基于所确定的内存分配类型,查询所述空闲大页链表或者所述空闲小页链表;
26.从对应的空闲大页链表或者空闲小页链表中取出一个页面,基于所确定的内存分配类型,将取出的页面划分为大小相同的内存块,并将划分为内存块的页面连接到对应的页面空闲链表中;
27.再执行从对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块的操作。
28.根据本发明提供的一种基于远程直接内存访问的内存管理方法,还包括:
29.判断对应的空闲大页链表或者空闲小页链表是否为空;
30.若对应的空闲大页链表或者空闲小页链表非空,从对应的空闲大页链表或者空闲小页链表中取出一个页面;
31.若对应的空闲大页链表或者空闲小页链表为空,查询所述线程堆链表;
32.判断所述线程堆链表是否存在未作为大页或者划分为小页的空闲的子段;
33.若所述线程堆链表存在空闲的子段,基于所确定的内存分配类型,将一个空闲的
子段作为一个大页或者划分为八个小页,并将所得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表中;
34.再执行从对应的空闲大页链表或者空闲小页链表取出一个页面的操作;
35.若所述线程堆链表不存在空闲的子段,判断所述线程堆链表是否存在未划分为子段的空闲的内存段;
36.若所述线程堆链表存在空闲的内存段,将一个空闲的内存段划分为四个子段;
37.再执行基于所确定的内存分配类型,将一个空闲的子段作为一个大页或者划分为八个小页,并将所得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表中的操作
38.若所述线程堆链表不存在空闲的内存段,向所述全局堆链表申请内存段。
39.根据本发明提供的一种基于远程直接内存访问的内存管理方法,还包括:
40.针对每一线程堆链表,将所述页面空闲链表中的每个页面中的空闲块连接成所述页面的空闲块链表;
41.响应于所述线程接收到内存块释放请求,基于请求释放的内存块的地址确定请求释放的内存块所在的目标内存段;
42.判断所述目标内存段的头部存储的所述目标内存段所在线程堆链表的头指针与所述线程的线程堆链表的头指针是否一致;
43.若所述目标内存段的头部存储的线程堆链表的头指针与所述线程的线程堆链表的头指针一致,为同线程内存释放,查询所述页面链表组,判断请求释放的内存块所在的页面是否在对应的页面空闲链表中;
44.若请求释放的内存块所在的页面在对应的页面空闲链表中,将请求释放的内存块连接到其所在的页面的空闲块链表中;
45.若请求释放的内存块所在的页面在对应的页面使用链表中,将请求释放的内存块所在的页面连接到对应的页面空闲链表中;
46.若所述目标内存段的头部存储的线程堆链表的头指针与所述线程的线程堆链表的头指针不一致,为跨线程内存释放,将请求释放的内存块连接到所述目标内存段的头部存储的跨线程释放链表指针指向的跨线程释放链表中。
47.根据本发明提供的一种基于远程直接内存访问的内存管理方法,,还包括:
48.判断请求释放的内存块所在的页面中的所有内存块是否均为空闲状态;
49.若请求释放的内存块所在的页面中的所有内存块均为空闲状态,将请求释放的内存块所在的页面连接到对应的空闲大页链表或者空闲小页链表中;
50.判断连接到所述空闲小页链表中的小页所在的子段中的所有小页是否均为空闲状态;或者,判断所述空闲大页链表的长度是否超过预先设定的阈值:
51.若连接到所述空闲小页链表中的小页所在的子段中的所有小页均为空闲状态,将所述子段中的所有小页从所述空闲小页链表中删除;若所述空闲大页链表的长度超过预先设定的阈值,从所述空闲大页链表中删除大页,使所述空闲大页链表的长度不超过预先设定的阈值;
52.所述基于所确定的内存分配类型,查询所述空闲大页链表或者所述空闲小页链表,包括:
53.遍历所述线程堆链表中的所有内存段,并依次对所述线程堆链表中内存段的头部存储的跨线程释放链表的指针指向的跨线程释放链表中的内存块进行释放;
54.若当前内存段所释放的跨线程释放链表中的内存块的大小符合所确定的内存分配类型,或者当前内存段所释放的跨线程释放链表中的内存块形成符合所确定的内存分配类型的空闲页面,则停止对所述线程堆链表中的内存段的遍历,进行内存块的分配;
55.若遍历所述线程堆链表中所有内存段所释放的跨线程释放链表中的内存块的大小均不符合所确定的内存分配类型,或者,遍历所述线程堆链表中所有内存段所释放的跨线程释放链表中的内存块未形成符合所确定的内存分配类型的空闲页面,则基于所确定的内存分配类型,查询所述空闲大页链表或者所述空闲小页链表。
56.根据本发明提供的一种基于远程直接内存访问的内存管理方法,所述基于所获得的内存区域的地址,按照8mib将所述内存区域划分为内存段之前,包括:
57.基于所获得的内存区域的地址,为每个rdma设备构建一颗内存区域地址树,以每次获得的内存区域作为树的叶子节点,以所述内存区域的启始地址和结束地址分别作为所述叶子节点的父节点和以所述父节点作为子节点时的父节点。
58.第二方面,本发明还提供一种电子设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机程序,所述处理器执行所述程序时实现如上述第一方面所述基于远程直接内存访问的内存管理方法的步骤。
59.第三方面,本发明还提供一种非暂态计算机可读存储介质,其上存储有计算机程序,该计算机程序被处理器执行时实现如上述第一方面所述基于远程直接内存访问的内存管理方法的步骤。
60.第四方面,本发明还提供一种计算机程序产品,其上存储有计算机程序,该计算机程序被处理器执行时实现如上述第一方面所述基于远程直接内存访问的内存管理方法的步骤。
61.本发明提供的基于远程直接内存访问的内存管理方法,通过获取一个足够大的内存区域向rdma设备进行注册,减少了对mr注册的触发,避免了内存不足时频繁触发mr注册,而造成单次内存分配难以预知的较大时间消耗。同时,为每个线程分配内存,使内存分配和释放的所有操作基本都是通过单线程实现,避免了多线程并发操作的性能消耗和安全风险,容易优化和验证,可以保证远程直接内存访问的速度和稳定性,保证远程直接内存访问的性能。
附图说明
62.为了更清楚地说明本发明或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作一简单地介绍,显而易见地,下面描述中的附图是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
63.图1是本发明提供的基于远程直接内存访问的内存管理方法的流程示意图;
64.图2是本发明提供的线程堆链表中一个内存段的结构示意图;
65.图3是本发明提供的另一个内存分配的流程示意图;
66.图4是本发明提供的线程堆链表的结构示意图;
67.图5是本发明提供的又一个内存分配的流程示意图;
68.图6是本发明提供的再一个内存分配的流程示意图;
69.图7是本发明提供的另一基于远程直接内存访问的内存管理方法的流程示意图;
70.图8是本发明提供的另一内存释放的流程示意图;
71.图9是本发明提供的在内存分配过程中进行内存释放的流程示意图;
72.图10是本发明提供的跨线程释放链表的结构示意图;
73.图11是本发明提供的又一基于远程直接内存访问的内存管理方法的流程示意图;
74.图12是本发明提供的一棵内存区域地址树的示意图;
75.图13是本发明提供的异形内存段的结构示意图;
76.图14是本发明提供的电子设备的结构示意图。
具体实施方式
77.为使本发明的目的、技术方案和优点更加清楚,下面将结合本发明中的附图,对本发明中的技术方案进行清楚、完整地描述,显然,所描述的实施例是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
78.下面结合图1-图13描述基于远程直接内存访问的内存管理方法。
79.请参阅图1,图1是本发明提供的基于远程直接内存访问的内存管理方法的流程示意图,图1所示的基于远程直接内存访问的内存管理方法可以由内存分配器执行,例如内存分配器可以采用dmalloc函数来实现,本发明实施例对此不作限定,如图1所示,该基于远程直接内存访问的内存管理方法至少包括:
80.101,向计算机系统申请内存区域,获得计算机系统分配的内存区域的地址,并将所获得的内存区域的地址注册到计算机系统的rdma设备中。
81.在本发明实施例中,在计算机通过远程直接内存访问传输数据时,需要先通过内存分配器向计算机系统申请内存区域,在内存分配器获得计算机系统分配的内存区域的地址之后,内存分配器会将所获得的内存区域的地址注册到计算机系统的rdma设备中,例如rdma设备可以为网卡,也就是将所获得的内存区域注册为mr(memory region),从而获得本地和远程访问所需要的凭证lkey和rkey,在每一次对所注册的内存区域的输入或者输出操作时都需要指定对应的key,这些key被内存分配器保存和分发。本发明实施例对内存分配器获得计算机系统分配的内存区域的地址的实现方法不作限定,例如,在linux下,内存分配器可以使用mmap获得计算机系统分配的内存区域的地址。考虑到性能,内存分配器每次获得的内存区域通常至少为几个gib。考虑到内存段需要对齐到8mib,在从计算机系统获取内存区域的地址时,内存分配器可以获取预期大小加上8mib的内存区域的地址,以确保对齐后内存区域的大小仍然符合预期。为了保证性能,内存分配器可以提供在mmap时指定大页内存的选项。
82.102,基于所获得的内存区域的地址,按照8mib将内存区域划分为内存段,并将每个内存段划分为头部和可用内存部,在头部设置链表指针,将划分得到的内存段连接成全局堆链表。
83.在本发明实施例中,在内存分配器将所获得的内存区域注册为mr之后,内存分配
器会按照8mib大小和8mib对齐将注册的内存区域划分为内存段segment,可以将划分得到的每个内存段分为头部和可用内存部,可以在划分得到的每个内存段的头部设置链表指针,通过链表指针将划分得到的内存段连接成一个全局堆链表,内存分配器持有这个全局堆链表的头指针。全局堆链表可以设置一个锁,在从全局堆链表获取和归还内存段时,都需要首先获取这个锁,然后再通过对全局堆链表的头指针的操作进行链表的相应操作。
84.103,响应于远程直接内存访问的线程启动,从全局堆链表中为线程分配内存段,并在所分配的内存段的头部设置链表指针,将所分配的内存段连接成线程堆链表,将线程堆链表的头指针返回给线程。
85.在本发明实施例中,在计算机通过远程直接内存访问传输数据存在多个线程时,内存分配器在响应于每个线程启动之后,会从全局堆链表中为每个线程分配内存段,并在每个线程所分配的内存段的头部设置链表指针,通过链表指针将每个线程所分配的内存段连接成该线程的一个线程堆链表,并将线程堆链表的头指针返回给对应的线程。每个线程都具有一个线程堆链表,并管理本线程的内存分配请求。
86.104,响应于线程接收到内存块分配请求,将线程堆链表中的一个内存段划分为四个2mib的子段,并基于请求分配的内存块的大小,将划分得到的一个子段作为一个2mib的大页或者划分为八个256kib的小页。
87.在本发明实施例中,当用于远程直接内存访问传输数据的一个线程接收到内存块分配请求时,内存分配器会响应于该线程接收到内存块分配请求,将该线程的线程堆链表中的一个内存段划分为四个2mib大小的子段subsegment,并根据请求分配的内存块的大小,将划分得到的一个子段作为一个大小为2mib的大页page或者划分为八个大小为256kib的小页。其中,每个内存段中的第一个子段由于要存放内存段头部的数据,因此只能划分为七个小页。
88.105,基于与请求分配的内存块的大小相匹配的预先设定的内存分配类型,将大页或者一个小页划分为大小相同的内存块,选取一个内存块作为目标内存块,将目标内存块的地址返回给所述线程。
89.在本发明实施例中,在将线程堆链表中的一个内存段划分为子段,并将子段作为大页或者划分为小页之后,内存分配器可以将请求分配的内存块的大小与预先设定的内存分配类型进行匹配,确定与请求分配的内存块的大小相匹配的内存分配类型,并根据所确定的内存分配类型将大页或者一个小页划分为大小相同的内存块,并从划分得到的内存块中选取一个内存块作为目标内存块,将目标内存块的地址返回给对应的线程。
90.在本发明实施例中,预先设定的内存分配类型可以为预先设定的内存分配大小的类型,可以将内存分配大小分为39个类型,分别为小于32b,类型,可以将内存分配大小分为39个类型,分别为小于32b,类型,可以将内存分配大小分为39个类型,分别为小于32b,此时只有小于2mib的内存分配大小才被支持,每个类型被分配为相同大小的内存块,这个大小为该类型大小的最大值,例如127b和128b对应的内存分配大小的类型都是65b~128b,分配出来的内存块的大小都是128b。
91.在本发明实施例中,设置了两种大小的页,即2mib的大页和256kib的小页。其中,
2mib大小的页面是必需的,否则不能提供2mib大小的内存块;而设置256kib大小的页面的原因主要有以下两个:一个是对于太小的分配大小,例如32b,共需要65536个块才能塞满一个2mib的页面,整个系统中可能都没有这么多对这个大小的块的需求,这就造成了浪费;另一个是每个内存段的头部需要存放一些内存段的管理信息,所以内存段的第一个2mib的子段在存放头部的管理信息后不能再作为一个完整的2mib的大页,只能划分为七个小页。
92.本发明实施例提供的基于远程直接内存访问的内存管理方法,通过获取一个足够大的内存区域向rdma设备进行注册,减少了对mr注册的触发,避免了内存不足时频繁触发mr注册,而造成单次内存分配难以预知的较大时间消耗。同时,为每个线程分配内存,使内存分配和释放的所有操作基本都是通过单线程实现,避免了多线程并发操作的性能消耗和安全风险,容易优化和验证,可以保证远程直接内存访问的速度和稳定性,保证远程直接内存访问的性能。
93.并且,可以减少内存碎片的数量,针对网络传输常用的内存大小规格,对于4k到512k之间的内存,由于内存分配类型的步进大小为1/4,因此内部碎片率总是小于25%;因为页大小相对较大,外部碎片率小于12.5%。对于其他分配大小,内存碎片率小于50%,外部碎片率为0;其他分配大小的50%的内部碎片率问题并不大,因为对于小于4k的分配大小,比较少且生命周期通常比较短,内存浪费是可以接受的;对于较大的内存分配需求,通常数量也不多。
94.另外,在rdma设备注册一个足够大的内存区域,使得mr的数量较少,也可以提升对mr查询的速度。
95.其中,内存碎片是指在内存分配过程中产生的不可使用的内存,可以分为内部碎片和外部碎片,举例来说,对于一个33k的内存分配需求,若分配一个40k的内存块,而40k内存块是在一个256k的页面上,该页面最多放置6个块,这样页面上剩余的256-40*6=16k的内存是不能被利用的,称为外部碎片,而内存块内40k-33k=7k的内存被分配出来也不能被利用的,称为内部碎片。
96.请参阅图2,图2是本发明提供的线程堆链表中一个内存段的结构示意图,如图2所示,每个segment的大小是8mib,包含四个大小为2mib的subsegment,每个subsegment包含1个大小为2mib的大页或者8个大小为256kib的小页,一个小页又包含8个大小为32kib的内存块,其中,在第一个subsegment中存放了segment头部的数据,所以只能包含7个256kib的小页。
97.请参阅图3,图3是本发明提供的另一个内存分配的流程示意图,如图3所示,该内存分配的流程至少包括:
98.301,响应于线程接收到内存块分配请求,基于预先设定的内存分配类型,确定与请求分配的内存块的大小相匹配的内存分配类型。
99.302,基于所确定的内存分配类型,查询页面链表组中对应的页面空闲链表。
100.303,判断对应的页面空闲链表中是否存在空闲内的存块。
101.若对应的页面空闲链表中存在空闲的内存块,执行304;若对应的页面空闲链表中不存在空闲的内存块,执行305。
102.304,从对应的页面空闲链表中的一个页面中取出一个空闲内存块作为目标内存块,将目标内存块的地址返回给线程。
103.305,将对应的页面空闲链表中的页面连接到对应的页面使用链表中。
104.在本发明实施例中,内存分配器可以针对每一线程的线程堆链表,将所划分的内存块的大小相同的页面,基于内存块的使用情况分别连接成页面空闲链表free_list和页面使用链表full_list,形成页面链表组,其中,连接成页面空闲链表和页面使用链表的页面可以是大页,也可以是小页。请参阅图4,图4是本发明提供的线程堆链表的结构示意图,如图4所示,在页面链表组中针对每一种大小的内存块,均存在两个链表,一个为free_list,另一个为页面full_list,在图4中仅展示了页面链表组中大小为32b的内存块的free_list和full_list,其中free_list和full_list均是由被划分大小为32b的内存块的页面连接而成,free_list通常是由页面中存在处于空闲状态,即未被使用的内存块的页面连接而成,full_list是由页面中所有的内存块均处于使用状态的页面连接而成。
105.当用于远程直接内存访问传输数据的一个线程接收到内存块分配请求时,内存分配器会响应于该线程接收到内存块分配请求,将请求分配的内存块的大小与预先设定的内存分配类型进行匹配,确定与请求分配的内存块的大小相匹配的内存分配类型,然后根据所确定的内存分配类型,查询页面链表组中对应的页面空闲链表,并判断对应的页面空闲链表中是否存在空闲的内存块,若对应的页面空闲链表中存在空闲的内存块,从对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块,将目标内存块的地址返回给线程,若对应的页面空闲链表中不存在空闲的内存块,将对应的页面空闲链表中的页面连接到对应的页面使用链表中。
106.例如,可以通过接口函数heap_alloc(heap,size)-》addr从线程堆链表中分配一个内存块,接口函数首先根据请求分配的内存块的大小size确定对应的内存分配类型的类size_class,然后查询页面链表组中找到size_class对应的页面空闲链表free_list,若页面空闲链表free_list非空,则从页面空闲链表free_list的一个页面中取出一个空闲的内存块,作为目标内存块,将目标内存块的首地址返回给线程,若页面空闲链表free_list的页面中不存在空闲的内存块,则将页面连接到对应的页面使用链表full_list中。
107.请参阅图5,图5是本发明提供的又一个内存分配的流程示意图,如图5所示,该内存分配的流程至少包括:
108.501,判断对应的页面空闲链表是否为空。
109.若对应的页面空闲链表为空,执行502;若对应的页面空闲链表非空,执行504。
110.502,基于所确定的内存分配类型,查询空闲大页链表或者空闲小页链表。
111.503,从对应的空闲大页链表或者空闲小页链表中取出一个页面,基于所确定的内存分配类型,将取出的页面划分为大小相同的内存块,并将划分为内存块的页面连接到对应的页面空闲链表中。
112.505,从对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块。
113.504,判断对应的页面空闲链表中是否存在空闲的内存块。
114.在本发明实施例中,内存分配器可以针对每一线程的线程堆链表,将线程堆链表中未划分为内存块的大页连接成空闲大页链表,将线程堆链表中未划分为内存块的小页连接成空闲小页链表。请再参阅图4,线程堆链表中的空闲大页链表是将线程堆链表中所有未划分为内存块的2mib的大页连接而成,线程堆链表中的空闲小页链表是将线程堆链表中所
有未划分为内存块的256kib的小页连接而成,如图4所示,在线程堆链表中同时存在页面链表组、空闲大页链表、空闲小页链表和未划分的内存段segment。
115.当用于远程直接内存访问传输数据的一个线程接收到内存块分配请求时,内存分配器响应于该线程接收到内存块分配请求,在查询页面链表组中对应的页面空闲链表之后,可以判断对应的页面空闲链表是否为空,若对应的页面空闲链表非空,则进一步判断对应的页面空闲链表中是否存在空闲的内存块,若对应的页面空闲链表中存在空闲的内存块,则从对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块作为目标内存块,将目标内存块的地址返回给线程若对应的页面空闲链表为空,则可以根据所确定的内存分配类型,进一步查询空闲大页链表或者空闲小页链表,从对应的空闲大页链表或者空闲小页链表中取出一个页面,基于所确定的内存分配类型,将取出的页面划分为大小相同的内存块,并将划分为内存块的页面连接到对应的页面空闲链表中,再从此时对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块,将目标内存块的地址返回给线程。
116.例如,在通过接口函数heap_alloc(heap,size)-》addr从线程堆链表分中分配一个内存块时,接口函数在查询页面链表组中找到size_class对应的页面空闲链表free_list之后,可以判断所找到的页面空闲链表free_list是否为空,若页面空闲链表free_list非空,则从页面空闲链表free_list的一个页面中取出一个空闲的内存块,作为目标内存块,将目标内存块的首地址返回给线程,若页面空闲链表free_list为空,则根据size_class查询空闲大页链表或者空闲小页链表,其中若size_class小于256kib则查询空闲小页链表,否则查询空闲大页链表,若所查询的空闲大页链表或者空闲小页链表非空,则从链表的头部取出一个页面,根据size_class将取出的页面划分成size_class对应的大小的内存块,并将划分为内存块的页面连接到对应的页面空闲链表free_list的尾部,再从此时对应的页面空闲链表free_list的一个页面中取出一个空闲的内存块作为目标内存块,将目标内存块的首地址返回给线程。
117.请参阅图6,图6是本发明提供的再一个内存分配的流程示意图,如图6所示,该内存分配的流程至少包括:
118.601,判断对应的空闲大页链表或者空闲小页链表是否为空。
119.若对应的空闲大页链表或者空闲小页链表非空,执行608;若对应的空闲大页链表或者空闲小页链表为空,执行602。
120.608,从对应的空闲大页链表或者空闲小页链表中取出一个页面。
121.602,查询线程堆链表。
122.603,判断线程堆链表是否存在未作为大页或者划分为小页的空闲的子段。
123.若线程堆链表存在空闲的子段,执行607;若线程堆链表不存在空闲的子段,执行604。
124.607,基于所确定的内存分配类型,将一个空闲的子段作为一个大页或者划分为八个小页,并将所得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表中。
125.604,判断线程堆链表是否存在未划分为子段的空闲的内存段。
126.若线程堆链表存在空闲的内存段,执行606;若线程堆链表不存在空闲内的存段,执行605。
127.605,向全局堆链表申请内存段。
128.606,将一个空闲的内存段划分为四个子段。
129.在本发明实施例中,当用于远程直接内存访问传输数据的一个线程接收到内存块分配请求时,内存分配器响应于该线程接收到内存块分配请求,在查询空闲大页链表或者空闲小页链之后,可以判断对应的空闲大页链表或者空闲小页链表是否为空,若对应的空闲大页链表或者空闲小页链表非空,则从对应的空闲大页链表或者空闲小页链表中取出一个页面,若对应的空闲大页链表或者空闲小页链表为空,则可以进一步查询线程堆链表,并判断线程堆链表是否存在未作为大页或者划分为小页的空闲的子段,若线程堆链表存在空闲的子段,则根据所确定的内存分配类型,将线程堆链表中的一个空闲的子段作为一个大页或者划分为八个小页,并将所得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表中,再从此时对应的空闲大页链表或者空闲小页链表中取出一个页面。
130.若线程堆链表不存在空闲的子段,则可以进一步判断线程堆链表是否存在未划分为子段的空闲的内存段,若线程堆链表存在空闲的内存段,则将线程堆链表中的一个空闲的内存段划分为四个子段,并根据所确定的内存分配类型,将划分得到的一个子段作为一个大页或者划分为八个小页,并将所得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表中,再从此时对应的空闲大页链表或者空闲小页链表中取出一个页面,若线程堆链表不存在空闲的内存段,则向全局堆链表申请内存段。
131.例如,在通过接口函数heap_alloc(heap,size)-》addr从线程堆链表分中分配一个内存块时,接口函数在根据size_class查询空闲大页链表或者空闲小页链表之后,可以判断所查询的空闲大页链表或者空闲小页链表是否为空,若所查询的空闲大页链表或者空闲小页链表非空,则从对应的空闲大页链表或者空闲小页链表的头部取出一个页面,若所查询的空闲大页链表或者空闲小页链表为空,则查询线程堆链表,遍历线程堆链表中的内存段segment,尝试找到一个空闲的子段subsegment,将所找到的空闲的子段subsegment作为一个大页或者划分为八个小页,并将得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表的尾部,若未找到空闲的子段subsegment,则尝试找到一个空闲的内存段segment,并将所找到的空闲的内存段segment划分为四个子段subsegment,将一个子段subsegment作为一个大页或者划分为八个小页,连接到对应的空闲大页链表或者空闲小页链表的尾部,若未找到空闲的内存段segment,则向全局堆链表申请一个内存段segment。
132.在线程接收到内存块分配请求,内存分配器从线程堆链表中寻找空闲的内存块返回给线程时,若线程堆链表中的空闲的内存块不足,内存分配器回向全局堆链表申请新的内存段,在向全局堆链表申请新的内存段时,若全局堆链表为空,内存分配器会向计算机系统申请新的内存区域,当内存分配器再次向计算机系统申请新的内存区域时,计算机系统会遵循一定的策略向内存分配器分配内存区域,这个策略可以是在建立全局堆链表时设定的,例如,在策略中可以规定再次向内存分配器分配的内存区域的大小,或者在策略中可以规定计算机系统不再向内存分配器分配内存区域,等,本发明实施例对此不作限定。
133.请参阅图7,图7是本发明提供的另一基于远程直接内存访问的内存管理方法的流程示意图,如图7所示,该基于远程直接内存访问的内存管理方法至少包括:
134.701,响应于线程接收到内存块释放请求,基于请求释放的内存块的地址确定请求释放的内存块所在的目标内存段。
135.702,判断目标内存段的头部存储的目标内存段所在线程堆链表的头指针与该线程的线程堆链表的头指针是否一致。
136.若目标内存段的头部存储的线程堆链表的头指针与该线程的线程堆链表的头指针一致,执行703;若目标内存段的头部存储的线程堆链表的头指针与该线程的线程堆链表的头指针不一致,执行706。
137.703,为同线程内存释放,查询页面链表组,判断请求释放的内存块所在的页面是否在对应的页面空闲链表中。
138.若请求释放的内存块所在的页面在对应的页面空闲链表中,执行704;若请求释放的内存块所在的页面在对应的页面使用链表中,执行705。
139.704,将请求释放的内存块连接到其所在的页面的空闲块链表中。
140.705,将请求释放的内存块所在的页面连接到对应的页面空闲链表中。
141.706,为跨线程内存释放,将请求释放的内存块连接到目标内存段的头部存储的跨线程释放链表指针指向的跨线程释放链表中。
142.在本发明实施例中,内存分配器可以针对每一线程的线程堆链表,将页面空闲链表中的每个页面中的空闲块连接成该页面的空闲块链表,也就是说,页面空闲链表中的每个页面都具有对应的空闲块链表。当用于远程直接内存访问传输数据的一个线程接收到内存块释放请求时,内存分配器会响应于该线程接收到内存块释放请求,根据请求释放的内存块的地址确定请求释放的内存块所在的目标内存段,并判断目标内存段的头部存储的目标内存段所在线程堆链表的头指针与该线程的线程堆链表的头指针是否一致,若目标内存段的头部存储的线程堆链表的头指针与该线程的线程堆链表的头指针一致,则确定内存块的释放为同线程内存释放,可以通过查询页面链表组,进一步判断请求释放的内存块所在的页面是否在对应的页面空闲链表中,若请求释放的内存块所在的页面在对应的页面空闲链表中,将请求释放的内存块连接到其所在的页面的空闲块链表中,若请求释放的内存块所在的页面在对应的页面使用链表中,将请求释放的内存块所在的页面连接到对应的页面空闲链表中,若目标内存段的头部存储的线程堆链表的头指针与该线程的线程堆链表的头指针不一致,则确定内存块的释放为跨线程释放,可以将请求释放的内存块连接到目标内存段的头部存储的跨线程释放链表指针指向的跨线程释放链表中。
143.例如,可以通过接口函数heap_free(heap,ptr)-》void进行线程堆链表中内存块的释放,接口函数首先通过指针ptr找到请求释放的内存块所在的目标内存段segment,然后获取目标内存段segment中记录的线程堆链表的头指针heap,如果所获取的线程堆链表的头指针heap指向当前线程的线程堆链表,即与接口函数中的参数heap一致,则认为此次内存块的释放为同线程内存释放,或者本地释放,在当前线程的线程堆链表中找到请求释放的内存块对应的页面空闲链表free_list和页面使用链表full_list,若请求释放的内存块所在的页面在页面空闲链表free_list中,则将请求释放的内存块连接到其所在的页面的空闲块链表中,若请求释放的内存块所在的页面在页面使用链表full_list中,则将请求释放的内存块所在的页面连接到对应的页面空闲链表free_list的尾部,如果所获取的线程堆链表的头指针heap未指向当前线程的线程堆链表,即与接口函数中的参数heap不一致,则找到所获取的线程堆链表的头指针heap指向的跨线程释放链表,通过原子操作将请求释放的内存块连接到跨线程释放链表中。
144.请参阅图8,图8是本发明提供的另一内存释放的流程示意图,如图8所示,该内存释放的流程至少包括:
145.801,判断请求释放的内存块所在的页面中的所有内存块是否均为空闲状态。
146.若请求释放的内存块所在页面中的所有内存块均为空闲状态,执行802;否则,结束该流程。
147.802,将请求释放的内存块所在的页面连接到对应的空闲大页链表或者空闲小页链表中。
148.803,判断连接到空闲小页链表中的小页所在的子段中的所有小页是否均为空闲状态,或者判断空闲大页链表的长度是否超过预先设定的阈值。
149.若是,执行804;否则,结束该流程。
150.804,将该子段中的所有小页从空闲小页链表中删除,或者从空闲大页链表中删除大页,使空闲大页链表的长度不超过预先设定的阈值。
151.在本发明实施例中,当用于远程直接内存访问传输数据的一个线程接收到内存块释放请求时,内存分配器会在响应于该线程接收到内存块释放请求,将请求释放的内存块中的内容清除或者将请求释放的内存块所在的页面连接到该线程对应的页面空闲链表中之后,还可以进一步判断请求释放的内存块所在的页面中的所有内存块是否均为空闲状态,若请求释放的内存块所在的页面中的所有内存块均为空闲状态,则将请求释放的内存块所在的页面连接到对应的空闲大页链表或者空闲小页链表中,若是将小页连接到空闲小页链表中,则进一步判断连接到空闲小页链表中的小页所在的子段中的所有小页是否均为空闲状态,若连接到空闲小页链表中的小页所在的子段中的所有小页均为空闲状态,则将该子段中的所有小页从空闲小页链表中删除,若是将大页连接到空闲大页链表中,则进一步判断空闲大页链表的长度是否超过预先设定的阈值,若空闲大页链表的长度超过预先设定的阈值,则从空闲大页链表中删除大页,使空闲大页链表的长度不超过预先设定的阈值。
152.请参阅图9,图9是本发明提供的在内存分配过程中进行内存释放的流程示意图,如图9所示,该内存释放的流程至少包括:
153.901,遍历线程堆链表中的所有内存段,并依次对线程堆链表中内存段的头部存储的跨线程释放链表的指针指向的跨线程释放链表中的内存块进行释放。
154.902,若当前内存段所释放的跨线程释放链表中的内存块的大小符合所确定的内存分配类型,或者当前内存段所释放的跨线程释放链表中的内存块形成符合所确定的内存分配类型的空闲页面,则停止对线程堆链表中的内存段的遍历,进行内存块的分配。
155.903,若遍历线程堆链表中所有内存段所释放的跨线程释放链表中的内存块的大小均不符合所确定的内存分配类型,或者,遍历线程堆链表中所有内存段所释放的跨线程释放链表中的内存块未形成符合所确定的内存分配类型的空闲页面,则基于所确定的内存分配类型,查询空闲大页链表或者空闲小页链表。
156.在本发明实施例中,当判断对应的页面空闲链表为空,基于所确定的内存分配类型,查询空闲大页链表或者空闲小页链表时,会首先考虑释放线程堆链表中内存段记录的跨线程释放链表中的内存块。当用于远程直接内存访问传输数据的一个线程接收到内存块分配请求,内存分配器响应于该线程接收到内存块分配请求,基于所确定的内存分配类型,查询空闲大页链表或者空闲小页链表时,内存分配器可以首先遍历该线程的线程堆链表中
的所有内存段,并依次对线程堆链表中内存段的头部存储的跨线程释放链表的指针指向的跨线程释放链表中的内存块进行释放,并在将每个内存块释放之后,判断所释放的内存块的大小是否符合请求分配的内存块的大小对应的内存分配类型,或者判断所释放的内存块是否形成符合请求分配的内存块的大小对应的内存分配类型的空闲页面,若所释放的内存块的大小符合请求分配的内存块的大小对应的内存分配类型,或者所释放的内存块形成符合请求分配的内存块的大小对应的内存分配类型的空闲页面,则停止对线程堆链表中的内存段的遍历,进行内存块的分配,若遍历线程堆链表中所有内存段所释放的跨线程释放链表中的内存块的大小均不符合请求分配的内存块的大小对应的内存分配类型,或者遍历线程堆链表中所有内存段所释放的跨线程释放链表中的内存块未形成符合请求分配的内存块的大小对应的内存分配类型的空闲页面,则向全局堆链表申请内存段。
157.其中,跨线程释放链表中的内存块的释放,可以通过判断跨线程释放链表中的内存块所在的页面是否在页面空闲链表free_list中,若跨线程释放链表中的内存块所在的页面在页面空闲链表free_list中,则将跨线程释放链表中的内存块连接到其所在的页面的空闲块链表中,若跨线程释放链表中的内存块所在的页面在页面使用链表full_list中,则将跨线程释放链表中的内存块所在的页面连接到该线程对应的页面空闲链表free_list中。
158.例如,在通过接口函数heap_alloc(heap,size)-》addr从线程堆链表分中分配一个内存块时,接口函数在基于所确定的内存分配类型,查询空闲大页链表或者空闲小页链表时,可以首先遍历线程堆链表中所有的内存段segment,对每个内存段segment执行以下操作:1、通过原子指令获得跨线程释放链表的内容,同时将内存段segment的跨线程释放链表置为空;2、遍历跨线程释放链表,采用与本地释放相同的流程将链表中的内存块释放;3、如果所释放的内存块中有内存块的大小与请求分配的内存块的大小对应size_class相同,或者所释放的内存块形成了符合请求分配的内存块的大小对应size_class的空闲页面,则直接返回内存分配流程,否则继续遍历。
159.请参阅图10,图10是本发明提供的空闲块链表的结构示意图,如图10所示,本发明实施例的空闲块链表中的内存块,可以在每个内存块的头部设置一个链表指针,通过链表指针将内存块串连起来形成一个链表,空闲块链表为线程堆链表的一部分,每次线程在进行内存分配时都尝试从空闲块链表中取出一个指定大小的内存块。
160.在本发明的上述各实施例中,跨线程内存释放只涉及单个原子操作,速度很快;由于每个内存段足够大因此线程堆链表从全局堆链表中获取或者释放内存段的频率较低,平摊下来对性能的负面影响很小;当向rdma设备注册的内存区域不足时,可以在确定的时机进行补充;同时,除了跨线程内存释放和从全局堆链表中获取和释放内存段外,内存的分配和释放的所有操作都是本地单线程的,没有多线程并发操作的性能消耗和安全风险,容易优化和验证。
161.在本发明的上述各实施例中,在进行内存释放时,当将一个页面连接到对应的页面空闲链表free_list中时,这个页面也将被从对应的页面使用链表full_list中移除,而这个页面会被连接到页面空闲链表free_list的尾部,以避免页面空闲链表free_list的页面上只有一个空闲的内存块,在连接到链表的头部时容易发生在两个链表,即full_list和free_list之间的来回移动。在进行内存释放时,若一个页面中的所有内存块都被释放,可
以预先设定一个阈值,例如预先设定的阈值为3,当页面空闲链表free_list的长度超过预先设定的阈值时,将该页中的标记清除,连接到对应的空闲页链表中;如果页面空闲链表free_list的长度不超过预先设定的阈值,则将该页面连接到页面空闲链表free_list的尾部。
162.请参阅图11,图11是本发明提供的又一基于远程直接内存访问的内存管理方法的流程示意图,如图11所示,该基于远程直接内存访问的内存管理方法至少包括:
163.1101,向计算机系统申请内存区域,获得计算机系统分配的内存区域的地址,并将所获得的内存区域的地址注册到计算机系统的rdma设备中。
164.1102,基于所获得的内存区域的地址,为每个rdma设备构建一颗内存区域地址树,以每次获得的内存区域作为树的叶子节点,以内存区域的启始地址和结束地址分别作为叶子节点的父节点和以父节点作为子节点时的父节点。
165.1103,基于所获得的内存区域的地址,按照8mib将内存区域划分为内存段,并将每个内存段划分为头部和可用内存部,在头部设置链表指针,将划分得到的内存段连接成全局堆链表。
166.1104,响应于远程直接内存访问的线程启动,从全局堆链表中为线程分配内存段,并在所分配的内存段的头部设置链表指针,将所分配的内存段连接成线程堆链表,将线程堆链表的头指针返回给线程。
167.1105,响应于线程接收到内存块分配请求,将线程堆链表中的一个内存段划分为四个2mib的子段,并基于请求分配的内存块的大小,将划分得到的一个子段作为一个2mib的大页或者划分为八个256kib的小页。
168.1106,基于与请求分配的内存块的大小相匹配的预先设定的内存分配类型,将大页或者一个小页划分为大小相同的内存块,选取一个内存块作为目标内存块,将目标内存块的地址返回给所述线程。
169.在本发明实施例中,由于每个mr对应于一段内存区域和一个rdma设备,在一个进程需要通过多个rdma设备进行远程直接内存访问时,或者在rdma设备第一次注册内存之后又补充分配了新的内存区域时,进行远程直接内存访问的输入和输出操作,需要指定正确的mr,否则会现出错。通过内存分配器分配一段内存区域就需要获取一次对应的mr,因此这是一个频率非常高的操作,为了提高这个操作的速度,可以为每个rdma设备构建一棵内存区域地址树,以这些树构成一片内存区域森林。
170.可以在根据所获得的内存区域的地址,按照8mib将内存区域划分为内存段之前,内存分配器还可以基于所获得的内存区域的地址,为每个rdma设备构建一颗内存区域地址树,该内存区域地址树是以每次获得的内存区域作为树的叶子节点,以该内存区域的启始地址和结束地址分别作为该叶子节点的父节点和以该父节点作为子节点时的父节点。请参阅图12,图12是本发明提供的一棵内存区域地址树的示意图,如图12所示,该棵内存区域地址树包括两个内存区域,分别为a[a,b)和b[c,d)。在向rdma设备注册一个mr的时候应将该内存区域的启示地址和结束地址分别插入该设备的内存区域地址树,在插入之后需要平衡该内存区域地址树,平衡内存区域地址树的方法可以采用现有的二叉树的平衡方法,本发明实施例对此不作限定。
[0171]
在内存区域森林中查找内存区域的过程,可以首先通过rdma设备找到该设备对应
的内存区域地址树,这个过程可以通过查询哈希表来实现,然后以待查询的内存区域地址为查询依据,查询所找到的内存区域地址树,若查询内存区域地址树找到一个mr,说明对于当前rdma设备和内存地址,可以使用该mr进行rdma通信,若查询内存区域地址树未找到一个mr,说明对于该rdma设备,当前的内存区域地址未注册为mr,需要向反馈错误信息。
[0172]
本发明实施例通过构建内存区域地址树,并形成内存区域森林,在多mr和多rdma设备的情况下,可以实现对rdma设备的mr的快速准确查询,从而获得正确的mr。
[0173]
在实际的使用中,可能会出现线程热点转移,即在某一时刻线程分配了大量的内存,导致线程堆链表持有了大量的内存段segment,而接下来的某个时刻该线程分配操作大量减少而另一个线程出现了大量的分配。在一些情况下线程热点转移会造成系统的剩余内存明明可以应对当前的内存使用,但是因为热点线程不能获取到足够的内存段segment,从而导致内存不足或者超量使用。
[0174]
本发明实施例提供的基于远程直接内存访问的内存管理方法可以通过内存段segment归还机制解决该问题,即线程堆链表可以将当前使用量较小或者空闲的内存段segment归还给全局堆链表。首先通过内存整理遍历线程堆链表中的所有内存段segment,统计线程堆链表总的内存使用率,并将内存段segment按照块级别的使用率升序排列;然后如果有空闲的内存段segment直接归还给全局堆链表,之后选择合理数量的低负载内存段segment,将其标记为待回收状态,并将其中已经加入页面空闲链表free_list的页面从页面链表组中取出,后续内存分配将跳过这些页面;最后在下一次内存整理被触发时,将标记为待回收状态的内存段segment归还给全局堆链表。
[0175]
此时,一个尚未回到空闲状态的内存段segment归还给全局堆链表是安全的,因为此时内存段segment上的heap字段会被清空,此时任何的释放操作都将作为跨线程释放被放进跨线程释放链表中。
[0176]
在本发明实施例中,线程堆整理可以由用户触发,因为用户侧可以相对准确的感知压力的转移,基于线程堆整理的特点,也可以周期性自动触发。
[0177]
在实际的使用中,存储系统有时候会遇到较大且不规则的内存分配需求,例如iscsi在一些场景下会商议出1280kib的内存块大小,1280kib的分配需求会得到2048kib的内存块,这时候会有37.5%的空间浪费,如果此类分配很多那么会导致巨大的内存压力。
[0178]
本发明实施例提供的基于远程直接内存访问的内存管理方法为了应对这种常见但是不属于标准分配大小的内存分配请求,可以通过异形分配机制解决该问题,即异形分配机制使用异形内存段segment。
[0179]
异形内存段segment的大小仍然为8mib,其结构是一个内存段segment头部后连续放置按照256kib对齐的内存块,请参阅图13,图13是本发明提供的异形内存段的结构示意图,如图13所示,在内存块为1280kib的一个异形内存段segment中放置6个1280kib的内存块,相比于正常内存段segment中可以放置3个1280kib内存块,异形内存段segment的空间利用率多了一倍。
[0180]
异形内存段segment仍然具有页的结构,每个内存块对应一个页,在分配阶段当异形内存块分配被命中的时候,线程堆链表会尝试找一个相应大小的空闲异形页,如果没有就尝试找一个尚未被使用的内存段segment并将其标记为异形内存段segment,从中分配异形内存块。
[0181]
在异形内存块被释放的时候,如果一个异形内存段segment上所有的内存块被释放,就将该异形内存段segment恢复为普通内存段segment。
[0182]
图14示例了一种电子设备的实体结构示意图,如图14所示,该电子设备可以包括:处理器(processor)1410、通信接口(communicationsinterface)1420、存储器(memory)1430和通信总线1440,其中,处理器1410,通信接口1420,存储器1430通过通信总线1440完成相互间的通信。处理器1410可以调用存储器1430中的逻辑指令,以执基于远程直接内存访问的内存管理方法,该方法包括:
[0183]
向计算机系统申请内存区域,获得所述计算机系统分配的内存区域的地址,并将所获得的内存区域的地址注册到所述计算机系统的rdma设备中;
[0184]
基于所获得的内存区域的地址,按照8mib将所述内存区域划分为内存段,并将每个所述内存段划分为头部和可用内存部,在所述头部设置链表指针,将划分得到的内存段连接成全局堆链表;
[0185]
响应于远程直接内存访问的线程启动,从所述全局堆链表中为所述线程分配内存段,并在所分配的内存段的所述头部设置链表指针,将所分配的内存段连接成线程堆链表,将所述线程堆链表的头指针返回给所述线程;
[0186]
响应于所述线程接收到内存块分配请求,将所述线程堆链表中的一个内存段划分为四个2mib的子段,并基于请求分配的内存块的大小,将划分得到的一个子段作为一个2mib的大页或者划分为八个256kib的小页;
[0187]
基于与请求分配的内存块的大小相匹配的预先设定的内存分配类型,将所述大页或者一个所述小页划分为大小相同的内存块,选取一个所述内存块作为目标内存块,将所述目标内存块的地址返回给所述线程。
[0188]
此外,上述的存储器1430中的逻辑指令可以通过软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本发明各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:u盘、移动硬盘、只读存储器(rom,read-onlymemory)、随机存取存储器(ram,randomaccessmemory)、磁碟或者光盘等各种可以存储程序代码的介质。
[0189]
另一方面,本发明还提供一种计算机程序产品,所述计算机程序产品包括存储在非暂态计算机可读存储介质上的计算机程序,所述计算机程序包括程序指令,当所述程序指令被计算机执行时,计算机能够执行上述各实施例提供的基于远程直接内存访问的内存管理方法,该方法包括:
[0190]
向计算机系统申请内存区域,获得所述计算机系统分配的内存区域的地址,并将所获得的内存区域的地址注册到所述计算机系统的rdma设备中;
[0191]
基于所获得的内存区域的地址,按照8mib将所述内存区域划分为内存段,并将每个所述内存段划分为头部和可用内存部,在所述头部设置链表指针,将划分得到的内存段连接成全局堆链表;
[0192]
响应于远程直接内存访问的线程启动,从所述全局堆链表中为所述线程分配内存
段,并在所分配的内存段的所述头部设置链表指针,将所分配的内存段连接成线程堆链表,将所述线程堆链表的头指针返回给所述线程;
[0193]
响应于所述线程接收到内存块分配请求,将所述线程堆链表中的一个内存段划分为四个2mib的子段,并基于请求分配的内存块的大小,将划分得到的一个子段作为一个2mib的大页或者划分为八个256kib的小页;
[0194]
基于与请求分配的内存块的大小相匹配的预先设定的内存分配类型,将所述大页或者一个所述小页划分为大小相同的内存块,选取一个所述内存块作为目标内存块,将所述目标内存块的地址返回给所述线程。
[0195]
又一方面,本发明还提供一种非暂态计算机可读存储介质,其上存储有计算机程序,该计算机程序被处理器执行时实现上述各实施例提供的基于远程直接内存访问的内存管理方法,该方法包括:
[0196]
向计算机系统申请内存区域,获得所述计算机系统分配的内存区域的地址,并将所获得的内存区域的地址注册到所述计算机系统的rdma设备中;
[0197]
基于所获得的内存区域的地址,按照8mib将所述内存区域划分为内存段,并将每个所述内存段划分为头部和可用内存部,在所述头部设置链表指针,将划分得到的内存段连接成全局堆链表;
[0198]
响应于远程直接内存访问的线程启动,从所述全局堆链表中为所述线程分配内存段,并在所分配的内存段的所述头部设置链表指针,将所分配的内存段连接成线程堆链表,将所述线程堆链表的头指针返回给所述线程;
[0199]
响应于所述线程接收到内存块分配请求,将所述线程堆链表中的一个内存段划分为四个2mib的子段,并基于请求分配的内存块的大小,将划分得到的一个子段作为一个2mib的大页或者划分为八个256kib的小页;
[0200]
基于与请求分配的内存块的大小相匹配的预先设定的内存分配类型,将所述大页或者一个所述小页划分为大小相同的内存块,选取一个所述内存块作为目标内存块,将所述目标内存块的地址返回给所述线程。
[0201]
以上所描述的装置实施例仅仅是示意性的,其中所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本实施例方案的目的。本领域普通技术人员在不付出创造性的劳动的情况下,即可以理解并实施。
[0202]
通过以上的实施方式的描述,本领域的技术人员可以清楚地了解到各实施方式可借助软件加必需的通用硬件平台的方式来实现,当然也可以通过硬件。基于这样的理解,上述技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品可以存储在计算机可读存储介质中,如rom/ram、磁碟、光盘等,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行各个实施例或者实施例的某些部分所述的方法。
[0203]
最后应说明的是:以上实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;
而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的精神和范围。
技术特征:
1.一种基于远程直接内存访问的内存管理方法,其特征在于,包括:向计算机系统申请内存区域,获得所述计算机系统分配的内存区域的地址,并将所获得的内存区域的地址注册到所述计算机系统的rdma设备中;基于所获得的内存区域的地址,按照8mib将所述内存区域划分为内存段,并将每个所述内存段划分为头部和可用内存部,在所述头部设置链表指针,将划分得到的内存段连接成全局堆链表;响应于远程直接内存访问的线程启动,从所述全局堆链表中为所述线程分配内存段,并在所分配的内存段的所述头部设置链表指针,将所分配的内存段连接成线程堆链表,将所述线程堆链表的头指针返回给所述线程;响应于所述线程接收到内存块分配请求,将所述线程堆链表中的一个内存段划分为四个2mib的子段,并基于请求分配的内存块的大小,将划分得到的一个子段作为一个2mib的大页或者划分为八个256kib的小页;基于与请求分配的内存块的大小相匹配的预先设定的内存分配类型,将所述大页或者一个所述小页划分为大小相同的内存块,选取一个所述内存块作为目标内存块,将所述目标内存块的地址返回给所述线程。2.根据权利要求1所述的基于远程直接内存访问的内存管理方法,其特征在于,还包括:针对每一线程堆链表,将所划分的内存块的大小相同的页面,基于内存块的使用情况分别连接成页面空闲链表和页面使用链表,形成页面链表组;其中,所述页面为所述大页或者所述小页;响应于所述线程接收到内存块分配请求,基于预先设定的内存分配类型,确定与请求分配的内存块的大小相匹配的内存分配类型;基于所确定的内存分配类型,查询所述页面链表组中对应的页面空闲链表;判断对应的页面空闲链表中是否存在空闲的内存块;若对应的页面空闲链表中存在空闲的内存块,从对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块,将所述目标内存块的地址返回给所述线程;若对应的页面空闲链表中不存在空闲的内存块,将对应的页面空闲链表中的页面连接到对应的页面使用链表中。3.根据权利要求2所述的基于远程直接内存访问的内存管理方法,其特征在于,还包括:针对每一线程堆链表,将所述线程堆链表中未划分为内存块的大页连接成空闲大页链表,将所述线程堆链表中未划分为内存块的小页连接成空闲小页链表;判断对应的页面空闲链表是否为空;若对应的页面空闲链表非空,判断对应的页面空闲链表中是否存在空闲的内存块;若对应的页面空闲链表为空,基于所确定的内存分配类型,查询所述空闲大页链表或者所述空闲小页链表;从对应的空闲大页链表或者空闲小页链表中取出一个页面,基于所确定的内存分配类型,将取出的页面划分为大小相同的内存块,并将划分为内存块的页面连接到对应的页面空闲链表中;
再执行从对应的页面空闲链表中的一个页面中取出一个空闲的内存块作为目标内存块的操作。4.根据权利要求3所述的基于远程直接内存访问的内存管理方法,其特征在于,还包括:判断对应的空闲大页链表或者空闲小页链表是否为空;若对应的空闲大页链表或者空闲小页链表非空,从对应的空闲大页链表或者空闲小页链表中取出一个页面;若对应的空闲大页链表或者空闲小页链表为空,查询所述线程堆链表;判断所述线程堆链表是否存在未作为大页或者划分为小页的空闲的子段;若所述线程堆链表存在空闲的子段,基于所确定的内存分配类型,将一个空闲的子段作为一个大页或者划分为八个小页,并将所得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表中;再执行从对应的空闲大页链表或者空闲小页链表取出一个页面的操作;若所述线程堆链表不存在空闲的子段,判断所述线程堆链表是否存在未划分为子段的空闲的内存段;若所述线程堆链表存在空闲的内存段,将一个空闲的内存段划分为四个子段;再执行基于所确定的内存分配类型,将一个空闲的子段作为一个大页或者划分为八个小页,并将所得到的大页或者小页连接到对应的空闲大页链表或者空闲小页链表中的操作若所述线程堆链表不存在空闲的内存段,向所述全局堆链表申请内存段。5.根据权利要求4所述的基于远程直接内存访问的内存管理方法,其特征在于,还包括:针对每一线程堆链表,将所述页面空闲链表中的每个页面中的空闲块连接成所述页面的空闲块链表;响应于所述线程接收到内存块释放请求,基于请求释放的内存块的地址确定请求释放的内存块所在的目标内存段;判断所述目标内存段的头部存储的所述目标内存段所在线程堆链表的头指针与所述线程的线程堆链表的头指针是否一致;若所述目标内存段的头部存储的线程堆链表的头指针与所述线程的线程堆链表的头指针一致,为同线程内存释放,查询所述页面链表组,判断请求释放的内存块所在的页面是否在对应的页面空闲链表中;若请求释放的内存块所在的页面在对应的页面空闲链表中,将请求释放的内存块连接到其所在的页面的空闲块链表中;若请求释放的内存块所在的页面在对应的页面使用链表中,将请求释放的内存块所在的页面连接到对应的页面空闲链表中;若所述目标内存段的头部存储的线程堆链表的头指针与所述线程的线程堆链表的头指针不一致,为跨线程内存释放,将请求释放的内存块连接到所述目标内存段的头部存储的跨线程释放链表指针指向的跨线程释放链表中。6.根据权利要求5所述的基于远程直接内存访问的内存管理方法,其特征在于,还包括:
判断请求释放的内存块所在的页面中的所有内存块是否均为空闲状态;若请求释放的内存块所在的页面中的所有内存块均为空闲状态,将请求释放的内存块所在的页面连接到对应的空闲大页链表或者空闲小页链表中;判断连接到所述空闲小页链表中的小页所在的子段中的所有小页是否均为空闲状态;或者,判断所述空闲大页链表的长度是否超过预先设定的阈值:若连接到所述空闲小页链表中的小页所在的子段中的所有小页均为空闲状态,将所述子段中的所有小页从所述空闲小页链表中删除;若所述空闲大页链表的长度超过预先设定的阈值,从所述空闲大页链表中删除大页,使所述空闲大页链表的长度不超过预先设定的阈值;所述基于所确定的内存分配类型,查询所述空闲大页链表或者所述空闲小页链表,包括:遍历所述线程堆链表中的所有内存段,并依次对所述线程堆链表中内存段的头部存储的跨线程释放链表的指针指向的跨线程释放链表中的内存块进行释放;若当前内存段所释放的跨线程释放链表中的内存块的大小符合所确定的内存分配类型,或者当前内存段所释放的跨线程释放链表中的内存块形成符合所确定的内存分配类型的空闲页面,则停止对所述线程堆链表中的内存段的遍历,进行内存块的分配;若遍历所述线程堆链表中所有内存段所释放的跨线程释放链表中的内存块的大小均不符合所确定的内存分配类型,或者,遍历所述线程堆链表中所有内存段所释放的跨线程释放链表中的内存块未形成符合所确定的内存分配类型的空闲页面,则基于所确定的内存分配类型,查询所述空闲大页链表或者所述空闲小页链表。7.根据权利要求1至6任一项所述的基于远程直接内存访问的内存管理方法,其特征在于,所述基于所获得的内存区域的地址,按照8mib将所述内存区域划分为内存段之前,包括:基于所获得的内存区域的地址,为每个rdma设备构建一颗内存区域地址树,以每次获得的内存区域作为树的叶子节点,以所述内存区域的启始地址和结束地址分别作为所述叶子节点的父节点和以所述父节点作为子节点时的父节点。8.一种电子设备,包括存储器、处理器及存储在所述存储器上并可在所述处理器上运行的计算机程序,其特征在于,所述处理器执行所述程序时实现如权利要求1至7任一项所述基于远程直接内存访问的内存管理方法的步骤。9.一种非暂态计算机可读存储介质,其上存储有计算机程序,其特征在于,所述计算机程序被处理器执行时实现如权利要求1至7任一项所述基于远程直接内存访问的内存管理方法的步骤。10.一种计算机程序产品,其上存储有计算机程序,其特征在于,所述计算机程序被处理器执行时实现如权利要求1至7任一项所述基于远程直接内存访问的内存管理方法的步骤。
技术总结
本发明提供一种基于远程直接内存访问的内存管理方法和设备。其中方法包括:向计算机系统申请内存区域获得内存区域的地址,将内存区域的地址注册到计算机系统的RDMA设备中;基于内存区域的地址按照8MiB将内存区域划分为内存段,并将内存段连接成全局堆链表;响应于远程直接内存访问的线程启动,从全局堆链表中为线程分配内存段,并连接成线程堆链表,将线程堆链表的头指针返回给线程;响应于线程接收到内存块分配请求,将线程堆链表中的一个内存段划分为四个2MiB的子段,并将一个子段作为一个2MiB的大页或者划分为八个256KiB的小页,将一个大页或者小页划分为大小相同的内存块,选取一个内存块将其地址返回给线程。取一个内存块将其地址返回给线程。取一个内存块将其地址返回给线程。
技术研发人员:孙文全
受保护的技术使用者:北京志凌海纳科技有限公司
技术研发日:2021.11.29
技术公布日:2022/3/8