问题
在虚拟化系统中,虚拟机(Virtual Machine)在运行时的总内存大小通常是恒定的,但虚拟机内部的工作内存集(即主动访问的内存)通常是总内存的子集。内存过度使用[4,6,7,9,19,26,37,40,44]有助于缓解这个问题,它从虚拟机回收冷内存(即最近未访问的内存),并根据需要将内存重新分配给其他虚拟机,以提高内存利用率。
I/O透传是客户端通过DMA的方式直接读取数据。如图1,CPU通过MMU(内存管理单元)页表将GPA(访客物理地址)转换为HPA(主机物理地址),设备的DMA请求依赖于IOPT(I/O页表)将IOVA(I/O虚拟地址,通常与GPA相同)转换为HPA。在CPU侧,如果访问的GPA没有有效的页面表条目,则会触发页面故障,由系统管理程序修复页表中的内存映射,然后从触发页面故障的位置重新执行。在设备端,大多数现成的设备不支持这种机制。因此它们要求所有DMA请求必须始终成功,否则将导致DMA失败和操作系统崩溃。这意味着启用了I/O直通的VM对IOPT(I/O页错误)条目丢失没有容忍度[4,25,26,40]。
然而,广泛采用的I/O透传技术使得内存过度使用变得不直观,因为当I/O设备访问客户内存时,虚拟机监视器必须避免DMA(直接内存访问)失败。
现有方法局限性
已经存在一些解决方案,例如,IOPF(I/O页错误)可以通过允许从I/O设备侧触发的页面错误来修复DMA失败,vIOMMU和coIOMMU通过监视客户机中的DMA缓冲区来避免DMA失败。然而,这些解决方案都面临着由内存备份/回收机制引入的性能问题,即内存交换。
一些基于空闲页面的方法(例如Ballooning、Free Page Reporting、Hyperupcall)不涉及内存交换,但它们要么不是DMA安全的,要么引入很高的客户通信开销。
本文方法
在本文中,我们提出了V-Probe,这是一种高效的方法,用于实现启用了I/O透传的虚拟机的内存过度分配。
-
以客户空闲页面为目标,消除了内存交换的昂贵开销。使用了由客户端注入的辅助函数来主动检测客户空闲页面,避免了与客户端的通信开销。
-
不使用eBPF,而是使用原始二进制辅助函数,这避免了客户端操作系统中复杂的eBPF依赖关系。这种简单性使得该方法更容易部署。
-
使用软件故障隔离(SFI)技术 [13, 31, 38, 43, 48],对注入的二进制进行严格的基于规则的指令级检查,以防止恶意代码。
-
使用细粒度的页面元数据管理,不仅管理回收的空闲页面的内存映射,还监视它们对应的页面元数据。这使得V-Probe能够对客户端内存分配事件做出反应并防止潜在的DMA失败。
实验证明,对于内存回收和重新分配,V-Probe的开销在微秒级别,比Ballooning和基于IOPF的方法快两个数量级。我们的微基准测试和宏基准测试表明,V-Probe将内存过度分配对性能的影响限制在一个很低的水平。
实验
实验环境:Intel®Xeon®Platinum 8163 CPU,系统管理程序基于QEMU和KVM,内存分配器以2MB的粒度管理客户虚拟机的底层内存,客户运行Linux操作系统,每个操作系统配备了2个CPU内核和4GB主内存。
数据集:sysbench CPU工作负载,micro-benchmark、macro-benchmark
实验对比:操作时间、TCP吞吐量、UDP延迟、QPS(每秒查询数)
总结
针对虚拟机内存过度使用场景,I/O透传导致的DMA故障问题。现有方法会由于内存备份/回收导致性能低,或不能保证DMA安全,或引入高通信开销。作者提出V-Probe,利用对客户代码的分析主动检测客户空闲页面,避免了与客户的通信开销;利用细粒度的页面元数据管理,不仅管理回收的空闲页面的内存映射,还监视它们对应的页面元数据,使得能够对客户端内存分配事件做出反应并防止潜在的DMA失败。
局限性:需要对客户端源码进行分析来检测客户空闲页面,在云场景不适用。