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

2078                                                       软件学报  2024  年第  35  卷第  4  期


                 内存分配器视为多个        Heap  类的组合, 并提供灵活, 解耦合的       Heap  类自定义. Heap  类主要实现    3  种接口, 分别为
                 malloc (sz)/free (ptr)/get_size (ptr). 在构造内存分配器时, 用户只需要通过  C++ mix-in  机制混合多个  Heap  类即可
                 得到所需的内存分配器. 虽然         HeapLayer 能够定制出满足大部分应用场景的专用分配器, 但是它依然存在一些限
                 制. 例如, Heap  类内存请求传递的只有内存请求的大小或者释放的内存指针. 尽管 HeapLayer 能够快速构建出
                 malloc(3) 定义的内存分配器实现, 却无法实现更灵活的用户接口. 例如操作系统内存分配常用的接口并非                          malloc(3),
                 而是页对齐分配接口       page_alloc 与对象分配接口    kmalloc; 而在一些内存分区隔离的分配器中, 分配接口还需要传
                 入额外的核心     ID  作为可选参数以区分特定的         DRAM bank  和  CPU cache 组  [6−8] . 同时, HeapLayer 也没有提供同步
                 机制的抽象, 这意味着      HeapLayer 无法依据应用场景的需求与并发竞争程度定制最佳的线程同步方式. 例如, 在存
                 在大量竞争分散的锁时, CAS        自旋锁具有性能优势; 而在要求确定的最差情况执行时间的实时系统领域, 同步过
                 程需要使用公平锁, 它能保证等待锁的线程不会陷入饥饿; 在存在高度并发的                        NUMA  系统中, 基于委任的分层锁
                 通常更具性能优势      [9−15] . HeapLayer 依赖  C++标准库以及  C++模板提供的  mix-in [16] , 因而难以在无操作系统的裸机
                 环境或嵌入式实时操作系统环境下定制内存分配器. 此外, HeapLayer 在某些存在约束的编码场景下也无法应用,
                 如只有   C  编译器支持的嵌入式硬件平台以及禁止            C++编码的   Linux  内核编程.
                    针对当前内存分配框架存在的限制, 本文提出了一种新型可组合的定制化内存分配框架榫卯, 如图                                1  所示. 榫
                 卯框架基于可组合的函数式编程思想, 将内存分配器抽象为多个互不耦合的层级函数. 层级函数分为系统接口层,
                 基础层与用户接口层        3  大类. 开发人员能够通过组合已定义好的层级函数, 快速构建出所需要的专用动态内存分
                 配器, 从而避免手动编写内存分配器时可能出现的错误. 此外, 开发人员可以使用该框架内提供的库函数, 策略函
                 数与数据结构等基本构件编写并定制新的层级函数. 在编写过程中开发人员只需关注特定层函数的实现.

                                                                     内存请求示意          层级连接
                                          系统接口层 A
                                                                      策略填充
                                                                         ...
                                                                       错误处理策略
                                           基础层 B                     大小阶划分策略
                                                                   同步策略
                                                                      自旋锁 CAS-spin

                                                 基础层 C               排队自旋锁 ticket

                               [LARGE_SIZE,                            委任锁 ccsynch
                               MAX_ULONG)
                                                      基础层 D


                                         [MEDIUM_SIZE,  基础层 E
                                         LARGE_SIZE)
                                                   [0,
                                               MEDIUM_SIZE)

                                          用户接口层 F

                                                  图 1 榫卯内存框架示意图

                    与现有的内存分配框架相比, 榫卯框架的特点在于:
                    (1) 组合性更好. 榫卯框架以函数式编程思想审视内存分配流程, 通过构造可扩展的内存请求上下文来在层级
                 函数之间传递内存请求, 同时封装函数产生的副作用. 这使得榫卯框架能够自定义用户请求接口.
                    (2) 定制性更好. 榫卯框架为每一个层级函数扩展出策略槽, 用于插入一些可复用的策略函数, 例如大小阶
                 (size class) 的映射函数与保证线程安全的同步算法函数. 这些策略函数为榫卯框架提供了更高的自由度, 可以产
                 生更多的定制组合.
   495   496   497   498   499   500   501   502   503   504   505