Page 513 - 《软件学报》2024年第4期
P. 513
欧阳湘臻 等: 榫卯: 一种可组合的定制化内存分配框架 2091
的内存申请. 所有分配的内存对象被打乱顺序后发布到一个全局链表中由其他线程远程释放, 这样能尽可能耗尽
内存分配器的线程本地缓存. 测试总共 7 组, 每组对应的分配大小阶以 2 倍增长, 依次为 (16, 32, 64,…, 2048) 字
节. 由于各线程分配内存大小是非对称的, 分配都是针对一个大小阶的, 且绝大部分释放都是非申请线程处理的远
程释放, 线程间竞争得以最大化.
4.3 实验方法
● 平均执行时间和最大 RSS 的测量方法. 本文运行基准测试负载时使用 LD_PRELOAD 命令加载不同的内存
分配器动态库, 通过/usr/bin/time 命令测量程序执行时间以及执行过程中的最大 RSS (resident set size, 驻留集大
小). 基准测试程序执行时间越短说明内存分配器越快. 而 RSS 可认为是进程实际使用物理内存大小. 由于测试负
载中内存请求次数和大小通常是确定的, RSS 可视为分配器内存利用率的指标. RSS 越小说明分配器的内存利用
率越高.
● 最差情况内存请求延迟的测量方法. 由于测量内存请求延迟的行为本身会产生延迟, 本文无法精确测量每
一个内存分配器的最差情况内存请求延迟. 因此, 本文使用最差情况内存请求延迟时间分布的百分位数统计值作
为其指标. 具体的测量方法是: 使用榫卯框架构建出一个测量内存请求时间的库 wcet_stat_malloc, 该库为 malloc
增加一个 wcet_stat 统计层函数, 其结构为: malloc_heap::wcet_stat. 该库与测试程序静态链接后, 再加载动态内存
分配器库即可测量并统计内存请求延迟的百分位时间分布.wcet_stat 层函数通过硬件指令插桩测量内存申请和释
放的 CPU 周期, 考虑到测量函数本身的执行可能影响到内存请求的速度从而降低并发竞争程度, 例如在 x86 上读
取硬件周期计数器会产生读内存屏障 (read memory barrier) 阻止 CPU 的乱序执行, 本文使用每 8 次内存请求采样
1 次的方式降低测量对结果的影响. 同时, 为了尽可能排除内核调度器的影响因素, wcet_stat 层通过配置线程的核
心亲和性, 强制将创建的线程固定在每个 CPU 逻辑核心上. 此外, 为了简化测量时的结果存储, wcet_stat 使用了一
个周期数组记录结果, 测量数组的最大值的周期对应的时间为约为 1 048 576 ns, 超过最大值的请求时间被视为最
大值记录, 测量完成后将统计的所有 CPU 执行周期转换为微秒.
4.4 实验结果与分析
本文分别在 x86/64 和 aarch64 实验平台加载内存分配器动态库运行基准测试, 总共执行 5 轮, 由此计算平均
值与标准差, 得到的结果如图 5–图 8 所示. 其中图 5 和图 6 是执行时间的对比, 图中 x 轴是基准测试项, y 轴是归
一化的执行时间, 即各分配器执行时间与 wfslab 执行时间的比值, 比值越小意味着更好的性能. 图 7 和图 8 是最
大 RSS 的对比, 图中 y 轴是归一化的最大 RSS, 即各分配器 RSS 与 wfslab 最大 RSS 的比值, 比值越小说明内存利
用率越高. 本文计算了实验结果的平均执行时间与最大 RSS 的几何平均数, 结果同样以 wfslab 的数据为基础归一
化, 用于综合衡量各分配器的平均执行时间和内存利用率, 如表 4 所示.
为了对比采用内存漏洞缓解措施的安全分配器, 本文使用 scudo, smi, mhg, dh, wfslabs, hslabd 和 tlsfccsd 同样
运行了上述实验, 计算其实验结果的几何平均数, 如表 4 所示.
本文在 x86/64 与 aarch64 硬件平台分别运行了 8 次最差情况内存请求延迟微基准测试负载, 收集测量结果并
对结果求平均值和标准差, 结果如图 9、图 10 所示. 图 9、图 10 的横坐标为百分位数, 纵坐标是百分位数对应的
内存请求延迟, 单位为 μs. 图中描点的数据从左到右依次是最耗时的 10%, 1%,…, 0.000 1% 的内存请求延迟. 需要
注意的是, 由于 aarch64 平台运行 Android 系统, 系统中存在大量的内核线程和传感器产生的中断, 导致线程运行
过程中出现较多的抢占和上下文切换, 因此在 aarch64 平台上测得的部分分配器内存请求延迟的大小与标准差比
x86/64 硬件平台更高.
本文将依据实验结果, 围绕以下 5 个问题进行分析, 以说明榫卯框架的有效性.
● 问题 1: 对比 wfslab 分配器, 手动编码实现的 wfslabm 分配器与插入额外 fake 附加层的 wfslabfl 分配器, 说
明榫卯框架中函数组合的性能开销.
● 问题 2: 对比 tlsfcc 分配器与原始 TLSF 分配器, 说明定制同步策略能否带来性能提升.
● 问题 3: 对比 hslab 分配器与相似架构的通用内存分配器, 说明定制核心感知的线程缓存能否带来性能提升.