VMware ESX Server中的内存资源管理

摘要

VMware ESX Server 是一款设计用于在运行未修改的普通操作系统的虚拟机之间高效分配硬件资源的精简软件层。ESX Server 管理内存的几种新机制和策略:

  • 一种气球技术通过回收虚拟机操作系统认为价值最小的页面来管理内存。
  • 闲置内存税在保持性能隔离保证的同时,实现了高效的内存利用。
  • 基于内容的页面共享和热 I/O 页面重映射利用透明页面重映射来消除冗余并减少复制开销。

简介

ESX Server 的设计与 VMware Workstation 有显著不同,后者使用一种托管虚拟机架构,利用预先存在的操作系统提供便携的 I/O 设备支持。

例如,一个基于 Linux 的 VMM 拦截 VM 尝试从其虚拟磁盘读取扇区的操作,并向底层 Linux 主机操作系统发出 read() 系统调用以检索相应的数据。相比之下,ESX Server 直接管理系统硬件,提供显著更高的 I/O 性能和对资源管理的完全控制。

内存虚拟化

地址翻译:

  • 虚拟地址到物理地址:客户操作系统和应用程序使用虚拟地址,操作系统将这些虚拟地址翻译成物理地址。
  • 物理地址到机器地址:ESX Server 再将这些物理地址翻译成机器地址。这样,虚拟机感知到的物理地址实际上是映射到真实硬件内存上的一个抽象层。

pmap 和影子页表的一致性:

为了确保系统的正确运行,pmap 中的 PPN 到 MPN 的映射和影子页表中 VA 到 MPN 的映射必须保持一致。这意味着,当虚拟机更新其页表导致 PPN 到 MPN 的映射发生变化时,ESX Server 必须相应地更新影子页表中的映射。

  • pmap 数据结构:pmap 是 ESX Server 为每个虚拟机维护的一个数据结构,用于将虚拟机感知到的“物理”页号(PPNs)映射到实际的机器页号(MPNs)。这个映射确保了虚拟机访问的内存最终能正确映射到实际的硬件内存。
  • 影子页表(Shadow Page Tables):影子页表是 ESX Server 为处理器维护的页表,它包含了从虚拟地址(VAs)直接到机器地址(MPNs)的映射。影子页表的作用是替代虚拟机的实际页表,以确保内存访问请求能够正确地重定向到实际的物理内存。

由于影子页表中的映射结果会被硬件 TLB 缓存,普通的内存引用可以在没有额外开销的情况下执行。这是因为当虚拟机访问内存时,大多数情况下都能命中 TLB,从而直接得到 VA 到 MPN 的映射结果,无需额外的地址翻译步骤。

回收机制

页面替换

当内存超额分配时,ESX Server 通过引入额外的分页级别和采用元级页面替换策略,从一个或多个虚拟机中回收内存空间。这一过程涉及复杂的决策,包括选择回收内存的虚拟机和具体要回收的页面,以确保系统在高效利用内存资源的同时,保持良好的性能和稳定性。

双重分页问题:

页面 A 被 ESX Server 分页到宿主系统的交换区后,客户操作系统 (例如:Linux) 又尝试将页面 A 写入其虚拟交换设备。由于页面 A 已经在宿主系统的交换区,这就需要先将页面 A 从宿主系统的交换区调入物理内存,再写入虚拟交换设备,造成不必要的分页操作。

膨胀技术(ballooning)

膨胀技术通过在客户操作系统中加载一个小型膨胀模块来工作。这个膨胀模块可以作为伪设备驱动程序或内核服务运行。关键点如下:

  • 伪设备驱动程序或内核服务:膨胀模块在客户操作系统内部运行,看起来像是一个普通的驱动程序或内核服务。
  • 没有外部接口:这个模块在客户操作系统内部没有对外部的接口,只通过私有通道与ESX Server通信。

当ESX Server需要回收内存时,过程如下:

  • 膨胀:ESX Server指示膨胀模块在客户操作系统内部分配一定数量的物理页内存。这些内存页看起来像是被客户操作系统的应用程序使用,但实际上是被膨胀模块“锁定”的。这相当于减少了客户操作系统可用的内存,使得这部分内存可以被ESX Server重新分配给其他需要内存的虚拟机。
  • 收缩:当ESX Server不再需要这些内存时,它会指示膨胀模块释放之前分配的那些物理页。这会恢复客户操作系统的可用内存。

膨胀膨胀模块会增加客户操作系统内的内存压力,导致它调用其自己的本地内存管理算法。客户操作系统决定要回收哪些特定页面,并在必要时将它们分页到其自己的虚拟磁盘。

My helpful screenshot

需求分页

当膨胀不可行或不足以满足需求时,系统会退回到分页机制。内存通过分页到 ESX Server 的磁盘交换区进行回收,无需客户操作系统的参与。

ESX Server 的交换守护进程从高层策略模块接收每个虚拟机的目标交换级别信息。它负责选择候选页面并协调异步页面的交换到磁盘上的交换区。常规优化方法用于保持空闲槽位并聚集磁盘写入操作。

共享内存

透明页面共享

引入了透明页面共享作为消除虚拟机之间冗余页面副本的方法,例如代码或只读数据的副本。一旦识别出副本,多组客户“物理”页面将映射到同一个机器页面,并标记为写时复制(copy-on-write)。对共享页面的写操作会引发故障,生成一个私有副本。

不幸的是,Disco 需要对客户操作系统进行几处修改才能在创建冗余副本时识别它们。

基于内容的页面共享

ESX Server 采用了一种完全不同的页面共享方法。其基本思想是通过页面的内容来识别页面副本。

一个总结页面内容的哈希值被用作查找键,查找哈希表中已经标记为写时复制(COW)的页面条目。如果新页面的哈希值与现有条目匹配,那么页面很可能是相同的,尽管可能存在错误匹配。成功匹配后,页面内容的全面比较验证页面是否相同。

“Shares vs. Working Sets”(份额与工作集)

ESX Server采用了一种新的分配算法,该算法能够在保持内存性能隔离保证的同时,实现高效的内存利用。此外,引入了一个显式参数,使系统管理员能够控制这些相互冲突目标的相对重要性。

基于份额的分配

当一个客户需要更多空间时,替换算法选择一个牺牲客户,从其先前分配的空间中撤销一些内存。内存从拥有最少份额/每页的客户那里被撤销。使用经济类比,份额/每页比率可以解释为价格;撤销将内存从支付较低价格的客户重新分配给愿意支付更高价格的客户。

份额表示相对资源权利,取决于争夺资源的总份额数量。当某些分配未被充分利用时,客户按比例受益于额外资源。

空闲内存回收

纯粹的比例份额算法存在一个显著的局限性,拥有大量份额的空闲客户端可能会不必要地囤积内存,而份额较少的活跃客户端则在内存压力下受到严重影响。

ESX Server 通过引入空闲内存税来解决这个问题。基本思想是对于空闲页面收取的费用要比活跃使用的页面多。当内存稀缺时,页面将优先从未积极使用其全部分配的客户端中回收。税率指定了可以从客户端中回收的空闲页面的最大比例。

计算空闲内存

一种选择是使用每个客操作系统内的原生接口提取信息。然而,这在实际操作中并不可行,因为不同客操作系统使用的活动指标各不相同,并且这些指标通常关注于每个进程的工作集。

ESX Server使用统计采样的方法直接获得每个虚拟机的整体工作集估算,无需虚拟机的参与。

在每个采样周期的开始,会随机选择虚拟机的一小部分“物理”页面,选择是基于均匀分布的。每个被采样的页面通过使其关联的缓存映射(如硬件TLB条目和虚拟化的MMU状态)失效来进行跟踪。

当虚拟机下一次访问被采样的页面时,该访问会被拦截,以重新建立这些映射,这时一个被访问页面计数器t会被递增。在采样周期结束时,虚拟机主动访问内存的估计比例f为f=t/n。

分配策略

大多数操作系统都试图保持一定数量的空闲内存。例如,BSD Unix在剩余内存百分比低于5%时开始回收内存,并持续回收直到空闲内存百分比达到7%。ESX Server采用类似的方法,但使用四个阈值来反映不同的回收状态:高、软、硬和低,默认分别为系统内存的6%、4%、2%和1%。

在高状态下,空闲内存足够,不执行任何回收。在软状态下,系统使用膨胀来回收内存,并且仅在无法进行膨胀的情况下才使用分页。在硬状态下,系统依赖分页来强制回收内存。在极少数情况下,如果空闲内存暂时低于低阈值,系统将继续通过分页回收内存,并额外阻止超出其目标分配的所有虚拟机的执行。