Page 505 - 《软件学报》2024年第4期
P. 505

欧阳湘臻 等: 榫卯: 一种可组合的定制化内存分配框架                                                     2083



                                       策略 P x  :=func A     层级连接              策略槽 P i
                                              基础层 L n                    基础层 L n+1



                                                                策略槽 P j     策略槽 P k
                                                 策略 P y  :=func B


                                              图 2 榫卯内存框架层级组合示意图

                    综上所述, 本文从函数式编程视角出发定义内存分配器框架主要出于以下考量. 可组合性: 函数式编程允许使
                 用高阶复合函数组合现有的函数来产生新函数, 与面向对象编程中对类进行组合相比, 其组合粒度更低. 简洁性:
                 函数式编程允许使用更简洁, 抽象的函数模型语言描述或构造复杂的内存分配器. 验证友好: 层级函数的输出只与
                 其输入参数有关, 状态和副作用均被封装到内存请求上下文中, 因而更易于测试与验证.
                  2.2   榫卯框架的实现细节
                    本文基于标准      C  实现了榫卯内存分配框架. 榫卯框架尽可能将实现的复杂性转移到框架本身, 对于开发者而
                 言只需先引入已有层级, 使用策略填充该层, 并最终将各层连接起来即可, 如图                       3  所示的内存分配器构建示例. 在
                 榫卯内存分配框架下, 开发者仅需要数十行代码便可组合出一个复杂的, 带有尾部校验和检测及错误处理功能的
                 3  层架构的  malloc(3) 高性能内存分配器. 图       3  中构建的内存分配器使用抽象模型语言可以表示为: mmap_
                 heap(faa_heap_growth=1, threadlocal_heap_size=1GB)::buddy_glk(sync=spinlock, size_handle=[65536,
                 SIZE_MAX))::slab_wf(sizeclass=prime, size_handle=[0, 65536))::tail_chksum(chksum=xor)::malloc_socket.

                                 内存请求示意           层级连接        同步策略          // 引入错误处理策略
                                   策略填充                                     #include "policy/error/def_handle.h"
                                                               mutex        // 引入supermalloc的大小阶策略
                                                                            #include "policy/sizeclass/prime.h"
                                                                            // 引入spinlock同步策略
                                                               spinlock     #include "policy/sync/spinlock.h"
                 系统接口层                mmap_heap                             // 引入异或校验策略
                                                                            #include "policy/chksum/xor.h"
                                                                ...
                                                                            // 完成层级的定制
                                                                ...         // 定制tail_chksum层用于检查缓冲区溢出
                                                                            // 使用默认的错误处理和异或校验
                                                                            USE_ERRHANDLE(tail_chksum, default)
                                                                            USE_CHKSUM(tail_chksum, xor)
                                                            大小阶划分策略         #include "layer/block/tail_chksum.h"
                                      buddy_glk
                                                                ...         // 定制slab_wf层,处理0~65536字节的内存请求
                                                                            SIZE_HANDLE(slab_wf, 0, 65536)
                                                                            USE_SIZECLASS(slab_wf, prime)
                                                               log2b        #include "layer/block/slab_wf.h"
                   基础层                                                      // 定制buddy_glk层,处理65536字节以上的内存请求
                                            wfslab             prime
                                                                            SIZE_HANDLE(buddy_glk, 65536, SIZE_MAX)
                                                                            USE_SYNCH(buddy_glk, spinlock)
                                                                ...         #include "layer/block/buddy_glk.h"
                                                                            // 定制mmapheap层,使用原子加指令进行堆增长
                               [65 536,                                     // 设置线程一次性申请的虚拟内存大小
                             SIZE_MAX)                                      USE_FAA_HEAP(1)
                                          tail_chksum         校验策略
                                                                            USE_THREADLOCAL_HEAP_SIZE(1 << 30)
                                                                            #include "layer/os/mmapheap.h"
                                                                ...
                                                                            // 完成分配器的整体定义
                                  [0, 65 536)                               // 定义系统接口层
                                                                xor
                                                                            DEFINE_OSLAYER(mmapheap)
                                                                ...         // 连接各层完成复合
                 用户接口层               malloc_socket                          LAYER_COMPOSE(mmapheap, buddy_glk, slab_wf,
                                                                            tail_chksum, malloc_socket)
                                             图 3 使用榫卯框架构建动态内存分配器
   500   501   502   503   504   505   506   507   508   509   510