Back to blog

Clove: Object-Level CXL Memory Management in Managed Runtimes

一种面向托管语言运行时(如JVM)的对象级CXL内存管理系统,通过profile-guided对象热度追踪与对象压缩技术解决页内热度倾斜问题

Clove: Object-Level CXL Memory Management in Managed Runtimes

一、论文概述

项目内容
标题Clove: Object-Level CXL Memory Management in Managed Runtimes
作者Sam Son, Zhihong Luo, Wen Zhang, Sylvia Ratnasamy, Scott Shenker
机构UC Berkeley / ICSI, Berkeley, USA
论文arXiv:2605.20370
代码无公开仓库
发布2026-05-19
许可CC BY 4.0
页数12页(含参考文献15页),13个图表
领域Operating Systems (cs.OS); Programming Languages (cs.PL)

二、核心思想

问题定义

CXL(Compute Express Link)内存 tiering 系统中,现有方案主要基于虚拟内存,使用页面(4KB 或 2MB)作为热度追踪和数据迁移的粒度。然而,由于现代架构的页面尺寸远大于大多数程序对象,单个页面内可能包含多个访问频率差异巨大的对象——这种现象被称为页内热度倾斜(Intrapage Hotness Skew)。

即使采用最优的页面放置策略,也无法达到最优的快 tier 命中率。这一问题在使用 huge pages(2MB)时尤为严重:每个 2MB 页面包含约 7000 个 key-value 对,使得大多数页面因聚合热度而变为”温热”状态,导致命中率显著降低。

论文通过 Oracle 策略评估表明,在 10% 和 20% 的 fast-tier 容量比下,对象级管理相比 4KB 页面分别能获得 19.6 和 15.4 个百分点更高的快 tier 命中率。

为什么选择托管运行时?

传统对象级管理主要针对 C/C++ 等未托管语言,需要开发者重写数据结构或使用特殊编译器注解。Clove 的核心观察是:现有托管运行时(如 JVM、.NET CLR)已经提供了与对象级 CXL 管理高度相关的优化机制:

  1. 对象重定位:现代垃圾回收器(如 ZGC)已提供高效的对象移动和堆压缩机制
  2. 动态代码生成:JIT 编译框架支持在运行时观察程序行为并进行选择性代码插桩

解决方案概述

Clove 通过最小化扩展现有托管运行时来实现透明的对象级 CXL 管理,其核心设计包括:

  1. Profile-guided 对象热度追踪:利用 PEBS 硬件采样识别导致 L3 缓存缺失的”脱轨指令”,仅对这些指令对应的对象插入热度计数器
  2. 混合重定位方法:运行时负责将热对象紧凑排列到连续虚拟页面中,底层页面级系统负责物理页面迁移
  3. 精心的热对象压缩策略:通过热度阈值和区域选择水位线来控制压缩开销

三、技术架构

整体框架

Clove系统架构总览

Clove 的工作流程分为四个逻辑步骤:

  1. 在线分析:Profiler 使用 PEBS 收集 L3 缓存缺失样本,识别脱轨指令
  2. JIT 插桩:JIT 编译器将热度追踪逻辑插入脱轨加载指令前,在对象头中维护热度计数器 O.hot++
  3. 热对象压缩:在 GC 扫描阶段读取热度计数器,确定热度阈值,将超过阈值的对象重定位到专用区域
  4. 页面迁移:底层页面级系统检测到目标区域的页面变热后,将其迁移到本地内存

核心公式与设计要点

对象热度计数器(利用 JVM 对象头未使用的 16 位):

inc_counter(Register scr, Address header_addr) {
    movzwq %scratch, %ax       // 读取对象头
    cmp  %ax, $0xFFFF          // 检查是否达到上限
    je   equal                 // 若达到上限则跳过
    inc  %ax                   // 递增计数器
    movw %ax, 0x6(obj)         // 写回对象头
equal:
    ...                        // 脱轨加载指令
}

该逻辑仅需 5 行汇编代码,且分支方向仅在计数器精确达到上限时变化,完全由分支预测器处理。

热度阈值确定:

Clove 在 GC 对象图扫描期间计算热度直方图,使用指数桶(第 i 个桶包含计数器值在 [2^i, 2^(i+1)) 范围内的对象)。计算从热到冷的累积和,当累积和首次超过本地内存大小时,将该桶及以上的对象分类为热对象。

区域选择策略:

基于两个可配置的水位线(低水位 5%、高水位 50%):

  • 热对象比例低于低水位的区域:不值得处理(固定开销无法摊薄)
  • 热对象比例高于高水位的区域:不需要压缩(已足够热)
  • 仅选择热对象比例在两个水位线之间的区域进行额外重定位

模型组件

组件说明关键参数
在线 Profiler使用 PEBS 收集 L3 缓存缺失样本采样率 1/2000,衰减比 1/2,每 1M 样本更新
热度追踪插桩在脱轨加载指令前插入计数器递增逻辑利用对象头未使用的 16 位空间
周期激活背景线程每 N ms 激活 1ms 的热度追踪N=8/16/32 时无明显开销
热度阈值决策基于直方图和本地内存容量动态确定指数桶 [2^i, 2^(i+1))
区域选择基于热对象比例的 watermark 策略低水位 5%,高水位 50%
混合重定位运行时压缩热对象 + 页面级迁移物理页ZGC 2MB 区域

训练/运行流程

Clove 的运行流程:

┌─────────────────────────────────────────────────────────────┐
│                      应用执行中                               │
│                                                             │
│  PEBS采样 → 识别脱轨指令 → JIT插桩 O.hot++                  │
│       ↓                                                       │
│  GC扫描 → 读取热度计数器 → 构建直方图 → 确定阈值            │
│       ↓                                                       │
│  区域选择 → 重定位热对象到专用区域                            │
│       ↓                                                       │
│  页面级系统检测热页面 → 迁移到本地内存                        │
└─────────────────────────────────────────────────────────────┘

四、核心创新

创新点说明理论/实验依据
Profile-guided 对象热度追踪不直接对对象采样,而是先识别导致 L3 缺失的少量指令,再仅追踪这些指令涉及的对象的访问PEBS 在 1/2000 采样率下即可接近 100% 的指令覆盖率,运行时开销 <1%
利用对象头存储计数器复用 JVM 对象头未使用的 16 位空间存储热度计数器,避免额外元数据存储仅需 5 条汇编指令,对象头通常在 L1 缓存中
周期激活机制用背景线程周期性更新激活标志替代每事件的条件检查,消除分支预测失败开销N=8/16/32 时几乎零开销,而均匀采样会导致不可预测的分支
混合重定位运行时负责热对象紧凑排列,页面级系统负责物理页迁移,职责分离无需运行时感知物理页位置,同时自然处理跨页大对象
双水位线区域选择基于热对象比例选择需要额外压缩的区域,平衡命中率提升与重定位开销低水位 5%、高水位 50% 在多种应用中均表现良好
对象头锁冲突优化采用乐观重试策略处理热度计数器更新与 CAS 锁操作的冲突经确认并发数据结构中无明显额外开销

五、代码实现分析

实现基础

Clove 基于 OpenJDK 21 原型实现,修改了三个核心组件:

  1. 在线 Profiler:作为 JVM 内的原生后台线程实现

    • PEBS 采样率:1/2000
    • 衰减比:1/2(每 1M L3 缺失样本)
    • 脱轨指令阈值:1%
  2. C2 JIT 编译器:修改了两个部分以插入插桩逻辑

    • 复用 ScopeDesc 数据结构,将脱轨指令的 IP 映射回原始字节码
    • 在字节码解析和代码生成阶段插入 Load IR 节点,在最终代码生成时注入热度追踪逻辑
    • 不干扰现有 C2 编译器优化
  3. ZGC(区域式无暂停垃圾回收器):扩展了三个阶段

    • 对象图遍历:读取热度计数器并构建直方图
    • 区域选择:基于热对象比例选择额外重定位区域
    • 重定位:将热对象移动到专用区域

关键技术细节

字节码到指令的映射:

字节码内存操作数格式偏移量
getfield[REG + offset]取决于字段
getstatic[REG + offset]静态字段偏移
getarraylength[REG + offset]数组长度偏移
aload_*[REG + offset]数组元素偏移

锁冲突处理:

当 CAS 操作失败时,检查对象头的低 48 位在 CAS 前后是否保持不变。如果不变,则判定为假失败并重试。

六、实验结果

评估设置

  • 测试平台:CloudLab c6420,双路 Intel Xeon Gold 6142,每路 192GB DDR4
  • CXL 模拟:通过 local-memory ballooning 机制模拟,测试 10%、20%、50% 三种本地内存比例
  • 基线系统:TPP(NUMA hint faults)、Memtis(PEBS + 动态大页拆分)、HybridTier(计数 Bloom 过滤器)
  • 应用:Ehcache(键值缓存)、JGraphT/PageRank(图算法)、H2/TPC-C(关系数据库)

端到端性能

合成工作负载性能

合成工作负载:

  • HotWarm 分布(20% 键占 90% 访问):在 20% 本地内存比例下,Clove 相比基线延迟降低 29-59%
  • Zipfian 分布(0.99):在 10% 和 20% 本地内存比例下仍有明显优势

真实工作负载性能

真实工作负载:

  • Ehcache + Twitter-Large(160GB):延迟降低 29-59%
  • Ehcache + Twitter-Medium(120GB):延迟降低 43-63%
  • JGraphT/PageRank(120GB):性能改进 47-84%
  • H2/TPC-C(120GB):延迟降低 22-47%

快 Tier 命中率

快Tier命中率

Clove 实现的本地内存命中率比 Memtis 高出 11-45 个百分点,且仅比理想 Oracle 策略低 4-5 个百分点,证明其实现了近最优的命中率。

页内热度倾斜量化

页内热度倾斜

Oracle 策略评估显示,对象级管理在 10% 和 20% 的 fast-tier 容量比下,相比 4KB 页面分别获得 19.6 和 15.4 个百分点的更高命中率。2MB huge pages 的表现最差,因为每个页面包含约 7000 个 key-value 对。

组件因子分析

在线 Profiler 开销:

Profiler开销

  • 在 1/2000 采样率下,指令覆盖率接近 100%
  • 运行时开销始终低于 1%

热度追踪 - 周期激活效果:

即使不启用周期激活,开销也仅为 4-5.5%(因为追踪逻辑本身很轻量)。周期激活(N=8/16/32)几乎消除了这一开销,而准确率几乎没有损失。

GC 开销:

GC开销

  • 额外的对象图扫描约每 6 分钟发生一次,持续 20-26 秒
  • 重定位阶段每两次扫描触发一次,持续 15-27 秒
  • 在 ZGC 下与应用程序并发执行,成本体现为缓存/内存争用而非停顿时间
  • 扫描期间归一化延迟短暂升至 1.2×,随后迅速恢复

动态适应性:

动态适应

与仅执行一次压缩的变体相比,Clove 的定期压缩能够持续适应热度变化,在第二次压缩后性能明显优于一次性方案。

压缩策略有效性:

热度阈值策略

  • 无阈值策略(No Cutoff)会将温对象与热对象一起压缩,降低低本地内存比例下的性能
  • 双水位线策略(5%/50%)在命中率和重定位时间之间取得了良好平衡

七、相关工作

类别代表工作与 Clove 的区别
页面级 CXL 管理TPP, Memtis, HybridTier, Nomad, FlexMem受限于页内热度倾斜,无法实现对象级精度
未托管语言对象级管理AIFM, MemLiner, OBASE需要开发者重写数据结构或使用编译器注解,不透明
硬件辅助子页管理PageSeer, Chameleon, MEMPod需要大量 SRAM 元数据,缺乏软件方案的灵活性
JVM 内细粒度内存管理Panthera, Semeru, Polar针对特定问题(NVM 写入寿命、Spark 放置等),非通用
本地内存作为 L4 缓存Johnny Cache需要硬件支持,缺乏灵活性

Clove 是唯一专注于托管语言运行时扩展以实现透明对象级 CXL 管理的系统。

八、总结

核心贡献

  1. 新设计方向:提出将现有托管语言运行时扩展为对象级 CXL 内存管理的新设计方向
  2. 挑战识别与解决:识别了托管运行时扩展到 CXL 管理的三大挑战(透明度、物理页可见性、对象重定位策略),并通过新颖的热度追踪、混合重定位和系统化热对象压缩来解决
  3. 原型验证:在 OpenJDK 21 上实现了 Clove 原型,在有偏斜访问模式的真实工作负载下,相比最先进的页面级系统减少应用延迟 22-84%,且无需源代码修改

技术影响

  • 证明了托管运行时中的 GC 重定位和 JIT 编译能力可以自然地复用于 CXL 内存管理
  • 为其他托管运行时(.NET CLR、PyPy、V8/SpiderMonkey)提供了可扩展的设计范式

局限性

  • 适用场景:针对热度在分钟到小时级别演变的内存密集型应用;每秒变化数百万/数十亿对象极端热度变化的工作负载不在范围内
  • 堆外内存:原生分配和 I/O 缓冲区不参与 GC 重定位,只能由底层页面级系统管理
  • 固定参数:当前使用固定的 PEBS 采样率、衰减比和水位线,自适应策略留作未来工作

九、参考资源