跳转至

配置 512 MiB 的 VM,实际占多少内存?

主要结论

配置 512 MiB 不等于宿主立即占用 512 MiB。在这组 64 MiB 应用工作集的静态测试中,默认 VM 与管理进程实际常驻约 179–181 MiB;内存卸载后约 36 MiB,每实例节约 80.0–80.4%;压缩卸载后约 40 MiB,节约 78.0–78.1%。包含文件缓存的产品组占用则从约 224 MiB 降到 19–25 MiB。 每个条件测一次,结论限于当前 Linux 配置与短观察窗口。

用户选择 这组数据说明什么
内存卸载 每实例节约 80.0–80.4% 常驻内存;含缓存的组占用也下降,下一次工具需要恢复 RAM
压缩卸载 每实例节约 78.0–78.1% 常驻内存;更省磁盘 backing,停驻常驻约 40 MiB
空闲释放 每实例节约 31.7–34.7% 常驻内存,但宿主仍保留文件缓存
内存压缩 重复内容每实例节约 18.9%;随机内容增加 18.2%,收益取决于可压缩性
共享快照+COW 相同内容平均每实例节约 67.9–68.6%,独有随机内容节约 31.2%;完整改写后仍节约 30.4–31.7%
KSM 观察 60 秒后,重复内容每实例节约 63.6%,相同随机内容节约 51.7%,独有随机内容节约 16.0%
daemon 内存池 每实例常驻约 61–124 MiB;重复 / 相同随机 / 独有随机内容的节约为 53.7% / 39.6% / 6.5%

实验动机

512 MiB 是 guest 可使用的容量,不是 VM 在宿主上已经占用的物理内存。选择压缩、卸载或共享时,需要看实际宿主占用,以及下一次工具的恢复代价。只看 guest 空闲量或压缩率,都不足以判断机器省下了多少 RAM。

实验设计

所有 VM 固定为 512 MiB guest RAM、2 vCPU、64 MiB 应用数据。工作集保持一致:实际占用取决于触及的页面,因此不假设默认 VM 会用满 512 MiB。

空闲释放由应用主动释放测试工作集,VM 继续运行,需要再次使用时重新生成数据。内存卸载暂停 VM,将 RAM 状态保留在未压缩的 backing 中并卸载常驻 RAM,恢复后继续执行。压缩卸载使用压缩 backing 保存相同状态,减少存储占用,增加压缩和解压的代价。

  • 单实例比较默认运行、空闲释放、内存压缩、内存卸载/压缩卸载。重复与确定性随机数据覆盖易压缩和难压缩内容;默认/内存压缩额外测可压缩的不同页面及 16 MiB 热区+48 MiB 冷区。
  • 跨实例比较原始不共享、共享快照+COW、KSM、daemon 内存池:原始组独立启动四台私有匿名 RAM VM;共享组从同一 sealed 快照恢复;KSM 组使用相同的 RAM 映射,并开启去重建议;内存池组独立启动 VM,由 daemon 持有跨实例重复的物理页面;读取保持共享,写入时生成实例私有页。独有候选不提前复制进池,写入后扫描回收旧引用。使用相同工作集,检查 25%/100% 改写和独立退出。
  • 每格一个新 VM 或新组,零预热。单实例观察 5 秒;KSM 在初始读数前观察 60 秒,其余跨实例方案观察 2 秒;不报告 P50/P95、置信区间或最终收敛。

常驻物理内存统计完整产品组的 VM、管理进程、压缩池/共享池和辅助进程,使用进程 PSS 之和,共享页面按比例计算。跨实例读数使用内核的进程汇总,避免逐映射取整;见 Linux 内存计量。宿主组内存使用完整 cgroup 的物理内存计费,包含计入该组的未映射文件缓存和内核开销。两个口径不能相加:前者回答进程实际常驻多少,后者防止忽略仍占 RAM 的缓存;共享页的归属方式也不同。两者都不等于整机新增的独占内存或生产容量。

Linux x86_64/KVM,AMD Ryzen 7 9700X,宿主内核 7.2.8-200.fc44.x86_64。完整组绑定逻辑 CPU 0–3、四核配额、零 swap;单实例组上限 2 GiB,跨实例四方案统一 4 GiB;协调器、观察者和全局 KSM 线程在组外。输入预先准备,不驱逐全局缓存;后台编译有记录,耗时仅为单次观察。单实例 16 个条件与新的跨实例 12 个条件分别来自独立静态批次,均通过数据、写入隔离、退出和来源检查,没有 OOM。

下面的命令设置 512 MiB VM 并开启对应功能。将 JOB、SOCKET、ATTEMPT 替换为启动输出中的身份。内存卸载从普通 VM 启动;压缩卸载先启用压缩 backing。内存压缩需要 userfaultfd 权限,压缩 backing 需要 FUSE。

# Default 512 MiB VM
pvisor run --executor vm --memory 512MiB -- claude

# Memory compression
pvisor run --executor vm --memory 512MiB --vm-cold-ram-compression -- claude

# Compressed backing for later offload
pvisor run --executor vm --memory 512MiB --vm-ram-compression -- claude

# Use the identities printed at startup
pvisor suspend JOB --vm-socket SOCKET --vm-job-id JOB --vm-attempt-id ATTEMPT --vm-offload
pvisor resume JOB --vm-socket SOCKET --vm-job-id JOB --vm-attempt-id ATTEMPT --vm-load

# KSM: without an explicit backing, Linux uses private anonymous RAM
pvisor run --executor vm --memory 512MiB --vm-ram-dedup -- claude

私有匿名 RAM 和恢复的私有 COW RAM 可以接受 KSM 建议;可写共享 RAM backing 会跳过。启用去重且不指定 backing 时,Linux 新 VM 使用私有匿名 RAM;该路径不支持整 VM offload。测试额外核验每台 VM 接受了去重建议,且 RAM 映射参与扫描,不能只凭命令接受就认定去重生效。共享基线数据也不代表四次独立 run。内存压缩与 RAM 去重不能组合,恢复的私有 COW RAM 不支持上述 live offload。详见控制选项和去重建议。

实验数据和分析

一台 512 MiB VM

每格 N=1,操作后 5 秒读数,单位 MiB。节约比例 =(默认实际常驻 − 当前实际常驻)÷ 默认实际常驻 × 100%,以相同工作集的默认运行作基准,用未舍入读数计算。512 MiB 是配置容量,不作为节约比例的分母。

方式 配置容量 实际常驻物理内存
重复内容 / 随机内容
每实例常驻节约比例
重复内容 / 随机内容
宿主组内存,含缓存
重复内容 / 随机内容
默认运行 512 181.4 / 179.4 基准 223.6 / 223.8
空闲释放 512 118.4 / 122.6 节约 34.7% / 31.7% 223.3 / 223.7
内存压缩 512 147.2 / 212.1 节约 18.9% / 增加 18.2% 131.2 / 195.8
内存卸载 512 35.6 / 35.8 节约 80.4% / 80.0% 19.4 / 19.2
压缩卸载 512 39.8 / 39.5 节约 78.1% / 78.0% 24.6 / 24.4

重复内容:64 MiB 应用数据由固定的字节序列反复填充,容易压缩,用于观察内容重复时的节约效果。随机内容:相同大小的数据由固定种子的伪随机序列填充,难以压缩,用于观察内容缺少重复时的效果。两种工作集的数据量相同,表头中的顺序对应每格的左右两个数值。

空闲释放后,常驻降至约 118–123 MiB,但含缓存占用仍约 223–224 MiB,因此不能宣称宿主已净回收同样多的 RAM。内存卸载同时降低两个读数,收益更明确。

内存压缩保持 VM 运行,只处理已驻留的冷块,保留未使用 RAM 的按需分配。重复内容常驻为 147.2 MiB,随机内容为 212.1 MiB;压缩不同页面为 146.4 MiB,冷热混合为 158.3 MiB,对应默认常驻为 179.8 / 177.8 MiB。扫描、编码和再次访问冷页时的解压消耗 CPU,节约取决于实际工作集。

卸载的存储与恢复代价

每格 N=1,耗时单位为 ms。先对比同样闲置 5 秒后、不卸载的默认 VM 执行相同测试任务的耗时。任务耗时从宿主发起操作开始,到完成 64 MiB 数据摘要、写入/fsync/读回校验为止;卸载组包含恢复 RAM 的时间。增加的耗时 = 卸载后任务耗时 − 相同工作集的不卸载任务耗时,使用未舍入读数计算。这是后台编译下的单次观测差值,不是稳定延迟保证。

方式 不卸载任务耗时 ms
重复内容 / 随机内容
卸载后恢复并完成任务 ms
重复内容 / 随机内容
增加的耗时 ms
重复内容 / 随机内容
内存卸载 276.5 / 320.1 432.4 / 498.2 +155.9 / +178.1
压缩卸载 276.5 / 320.1 1730.3 / 766.2 +1453.8 / +446.1

卸载操作发生在进入闲置状态时,另列如下;backing 为实际分配的磁盘块,单位 MiB。

方式 卸载操作 ms
重复内容 / 随机内容
backing MiB
重复内容 / 随机内容
内存卸载 44.1 / 98.1 186.4 / 186.3
压缩卸载 739.4 / 904.0 15.5 / 146.0

压缩 backing 在重复内容上更省存储,但需要编码、解码和临时内存。不要按停驻时的读数设置整个任务的内存上限;峰值、阶段 CPU 与完整样本口径保留在 CSV。

四台各 512 MiB 的 VM:方案对比

总配置容量为 2048 MiB。原始不共享是四台独立启动的 VM;共享快照+COW 使用同一个不可变 RAM 文件,修改时生成实例私有页;KSM 在独立启动的 VM 上开启内存去重建议。daemon 内存池从私有匿名 RAM 启动,把重复页面映射到池持有的同一份物理页;读取保持共享,写入使用 COW。除 KSM 组外,其余三组均未启用 KSM advice。

每实例常驻内存 = 完整产品组 PSS 合计 ÷ 4,包含分摊的辅助进程和 daemon 池组件开销。每格 N=1,单位 MiB。KSM 在初始读数前观察 60 秒,其余方案观察 2 秒;25%/100% 改写后的读数沿用统一短采样流程,没有再次等待 60 秒。节约比例以相同工作集、相同阶段的原始不共享组为基准,使用未舍入读数计算。

工作集 方案 每实例常驻 MiB 每实例节约比例 100% 改写后每实例常驻 MiB 改写后每实例节约比例
相同重复内容 原始不共享 132.8 基准 132.9 基准
相同重复内容 共享快照+COW 41.7 68.6% 91.2 31.3%
相同重复内容 KSM 48.4 63.6% 112.6 15.3%
相同重复内容 daemon 内存池 61.4 53.7% 128.2 3.5%
相同随机内容 原始不共享 132.3 基准 132.4 基准
相同随机内容 共享快照+COW 42.4 67.9% 92.2 30.4%
相同随机内容 KSM 64.0 51.7% 112.3 15.2%
相同随机内容 daemon 内存池 80.0 39.6% 128.9 2.7%
各实例独有随机内容 原始不共享 132.3 基准 133.7 基准
各实例独有随机内容 共享快照+COW 91.0 31.2% 91.3 31.7%
各实例独有随机内容 KSM 111.1 16.0% 111.2 16.9%
各实例独有随机内容 daemon 内存池 123.7 6.5% 125.6 6.1%

共享快照+COW 的收益包括共同系统状态和未改写的应用页面;完整改写 64 MiB 应用工作集后,系统页仍可能共享。独有随机内容会在准备阶段就增加私有页,因此初始节约较少。

KSM 在 60 秒内产生了实际页面合并;重复、相同随机、独有随机内容每实例常驻分别为 48.4/64.0/111.1 MiB。它合并实例内和跨实例的相同页面;独有随机数据仍需各自保存。完整改写会打破原来的共享页;改写后的读数没有再次等待 60 秒,不能代表重新收敛后的收益。每台 VM 都通过私有 RAM、去重建议接受字节和可合并标志检查。

daemon 内存池由宿主扫描跨实例重复的 4 KiB 页面,读取保持物理共享,写入使用 COW。 三种内容每实例常驻分别为 61.4/80.0/123.7 MiB,表中已计入池和辅助进程;完整组观测峰值为 537–546 MiB。扫描跳过未驻留页,只有实际回收的页才分配对象引用与校验信息,避免把配置容量转化成物理占用。独有候选只保留有界摘要,不搬入池;写入后扫描释放旧池引用。

物理共享池不压缩独有页,也不依赖 userfaultfd。相同内容读访问不会复制回私有 RAM;应用写入会生成私有页,再扫描时才回收旧引用。扫描、校验、页面传输、映射和管理信息仍消耗 CPU 与内存;因此专用方案并不保证胜过所有对照。共享快照从同一系统状态恢复,而池对照是独立启动的 VM,系统页能否共享取决于实际字节是否相同。改写后的短窗口只说明当时占用;池进程丢失会使依赖 VM 失败。

在 pvisor-daemon serve 命令中添加 --memory-pool 即可启用,默认关闭;池与 API 进程分离,可跨 API 重启保留对象。配置和预算见 daemon 指南。本轮测量的是实际 daemon 池组件与 VM 的路径,未启动完整 OpenSandbox API/SDK 数据面,不回答长期稳定性、真实 Agent 延迟或生产密度。

数据与复现

单实例读数 · 单实例观测差值 · 单实例来源 · 跨实例读数 · 跨实例观测差值 · 跨实例来源 · 复现命令

这些 CSV 只使用新的 512 MiB 静态批次,保留配置、N=1、常驻/缓存口径及源码、二进制、harness 和输入摘要关联。原始证据留在本地 .data/,不混入此前 256 MiB 或历史快照数据。