1 - 快照

cloud hypervisor 快照

1.1 - 快速开始

cloud hypervisor 快照快速开始

机器配置

安装好 cloud hypervisor,测试机器为 debian13 物理机器,intel x86-64 cpu。

$ cloud-hypervisor --version
cloud-hypervisor v50.0.0

$ ch-remote --version
ch-remote v50.0.0

$ uname -a
Linux skydev3 6.12.57+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.57-1 (2025-11-05) x86_64 GNU/Linux

内核

为了极致的启动速度和测试效率,推荐使用 Cloud Hypervisor 官方提供的测试资源,或者使用 Alpine Linux 这种极简发行版。

mkdir -p ~/work/test/cloudhypervisor
cd ~/work/test/cloudhypervisor

ch官方内核

linux kernel 采用之前构建的 x86 内核(45MB),方便起见复制到本地:

cp ~/work/code/cloud-hypervisor/linux-cloud-hypervisor/arch/x86/boot/compressed/vmlinux.bin .

这个内核版本是 6.12,非常新。

记录文件地址备用:

/home/sky/work/test/cloudhypervisor/vmlinux.bin

rootfs

ubuntu cloud image

兼容性最好,但是有点大:

# 下载 Ubuntu 24.04 (Noble) 云镜像
mkdir ubuntu-cloud-image
cd ubuntu-cloud-image
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img

# Cloud Hypervisor 需要 raw 格式,且需要解压
sudo apt install -y qemu-utils
qemu-img convert -p -f qcow2 -O raw noble-server-cloudimg-amd64.img rootfs.raw

# 调整大小(可选,云镜像默认只有 2GB 左右)
qemu-img resize rootfs.raw 4G

操作之后得到的 rootfs 为:

ls -lh                       
total 2.4G
-rw-rw-r-- 1 sky sky 598M Dec 13 21:20 noble-server-cloudimg-amd64.img
-rw-r--r-- 1 sky sky 4.0G Dec 30 17:07 rootfs.raw

记录文件路径备用:

/home/sky/work/test/cloudhypervisor/ubuntu-cloud-image/rootfs.raw

Alpine Linux

TODO

启动

启动 microvm:

sudo rm -rf /home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock
sudo /home/sky/work/soft/cloudhypervisor/bin/cloud-hypervisor \
    --api-socket /home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock \
    --cpus boot=1 \
    --memory size=4G \
    --kernel /home/sky/work/test/cloudhypervisor/vmlinux.bin \
    --cmdline "root=/dev/vda1 console=hvc0 rw" \
    --disk path=/home/sky/work/test/cloudhypervisor/ubuntu-cloud-image/rootfs.raw

在另外一个终端,先 pause:

sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock pause

再执行快照命令,快照文件输出到 snapshot-4g 文件夹:

mkdir -p snapshot-4g
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  snapshot file:///home/sky/work/test/cloudhypervisor/snapshot-4g

完成后可以看到:

ls -lh ./snapshot-4g

文件列表为:

total 4.1G
-rw------- 1 root root 1.4K Dec 30 17:23 config.json
-rw------- 1 root root 4.0G Dec 30 17:23 memory-ranges
-rw------- 1 root root  42K Dec 30 17:23 state.json

执行关闭命令,关闭这个 microvm

sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  resume
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  shutdown
sleep 1
sudo rm -rf /home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock

快照恢复

sudo /home/sky/work/soft/cloudhypervisor/bin/cloud-hypervisor \
    --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock \
    --restore source_url=file:///home/sky/work/test/cloudhypervisor/snapshot-4g

1.2 - 快照文件信息

cloud hypervisor 快照文件信息

文件列表

快照生成时,需要指定一个目录,然后会生成如下三个文件,以4G内存的虚拟机为例:

ls -lh
total 4.1G
-rw------- 1 root root 1.4K Dec 30 17:23 config.json
-rw------- 1 root root 4.0G Dec 30 17:23 memory-ranges
-rw------- 1 root root  42K Dec 30 17:23 state.json

config.json

config.json 格式化之后的内容:

{
  "cpus": {
    "boot_vcpus": 1,
    "max_vcpus": 1,
    "topology": null,
    "kvm_hyperv": false,
    "max_phys_bits": 46,
    "affinity": null,
    "features": {
      "amx": false
    },
    "nested": true
  },
  "memory": {
    "size": 4294967296,
    "mergeable": false,
    "hotplug_method": "Acpi",
    "hotplug_size": null,
    "hotplugged_size": null,
    "shared": false,
    "hugepages": false,
    "hugepage_size": null,
    "prefault": false,
    "zones": null,
    "thp": true
  },
  "payload": {
    "firmware": null,
    "kernel": "/home/sky/work/test/cloudhypervisor/vmlinux.bin",
    "cmdline": "root=/dev/vda1 console=hvc0 rw",
    "initramfs": null
  },
  "rate_limit_groups": null,
  "disks": [
    {
      "path": "/home/sky/work/test/cloudhypervisor/ubuntu-cloud-image/rootfs.raw",
      "readonly": false,
      "direct": false,
      "iommu": false,
      "num_queues": 1,
      "queue_size": 128,
      "vhost_user": false,
      "vhost_socket": null,
      "rate_limit_group": null,
      "rate_limiter_config": null,
      "id": "_disk0",
      "disable_io_uring": false,
      "disable_aio": false,
      "pci_segment": 0,
      "serial": null,
      "queue_affinity": null
    }
  ],
  "net": null,
  "rng": {
    "src": "/dev/urandom",
    "iommu": false
  },
  "balloon": null,
  "fs": null,
  "pmem": null,
  "serial": {
    "file": null,
    "mode": "Null",
    "iommu": false,
    "socket": null
  },
  "console": {
    "file": null,
    "mode": "Tty",
    "iommu": false,
    "socket": null
  },
  "debug_console": {
    "file": null,
    "mode": "Off",
    "iobase": 233
  },
  "devices": null,
  "user_devices": null,
  "vdpa": null,
  "vsock": null,
  "pvpanic": false,
  "iommu": false,
  "numa": null,
  "watchdog": false,
  "pci_segments": null,
  "platform": null,
  "tpm": null,
  "landlock_enable": false,
  "landlock_rules": null
}

这个 config.json 文件是 Cloud Hypervisor 在执行快照(Snapshot)时生成的,它记录了虚拟机在快照那一刻的静态配置信息。当恢复(Restore)快照时,Cloud Hypervisor 会读取这个文件来重建虚拟机的“骨架”(CPU、内存大小、磁盘路径等),然后再加载内存和设备状态。

关键配置解读:

CPU 设置 (cpus)

  • boot_vcpus: 1: 虚拟机启动时分配了 1 个 vCPU。
  • max_vcpus: 1: 最大也是 1,说明这台 VM 不支持 CPU 热插拔(如果要支持,max_vcpus 通常要大于 boot_vcpus)。
  • nested: true: 嵌套虚拟化已启用。这意味着您在这个 MicroVM 里面还可以运行 KVM(例如在 VM 里运行 Docker 或 QEMU)。这在测试环境中很有用。

内存设置 (memory)

  • size: 4294967296: 即 4GB (4 * 1024 * 1024 * 1024)。
  • hotplug_method: “Acpi”: 如果支持内存热插拔,将使用 ACPI 机制通知 Guest OS。
  • thp: true: 启用了 Transparent Huge Pages(透明大页),这通常有助于减少 TLB miss,提升内存访问性能。

启动载荷 (payload)

这是 Direct Kernel Boot 的核心配置。

  • kernel: /home/sky/work/test/cloudhypervisor/vmlinux.bin

    注意:这里记录的是绝对路径。如果把快照目录复制到另一台机器上去恢复,必须确保那台机器的相同路径下也有这个内核文件,否则恢复会失败。

  • cmdline: root=/dev/vda1 console=hvc0 rw

    • root=/dev/vda1: 指定根文件系统挂载点。
    • console=hvc0: 关键点。Cloud Hypervisor 默认使用 Virtio Console (hvc0) 而不是传统的串口 (ttyS0)。如果您在启动时看不到输出,需要检查 Guest OS 是否启用了 hvc0 的 getty 服务。

磁盘设备 (disks)

  • path: /home/sky/work/test/cloudhypervisor/ubuntu-cloud-image/rootfs.raw

    同样是绝对路径。恢复快照时,程序会去这个位置找磁盘文件。如果磁盘文件被删了或者移动了,恢复会报错。

  • readonly: false: 磁盘是可读写的。

  • direct: false: 没有开启 Direct I/O(O_DIRECT),意味着磁盘读写会经过宿主机的 Page Cache。

网络 (net)

  • null: 您启动这个虚拟机时没有配置网络接口。它是一个“单机”环境,无法联网。

控制台与串口 (console & serial)

  • console (Virtio Console):
    • mode: “Tty”。这意味着虚拟机的 hvc0 输出被重定向到了宿主机运行 cloud-hypervisor 进程的当前终端(TTY)。
  • serial (Legacy Serial):
    • mode: “Null”。传统的串口(ttyS0)被禁用了/未连接。这就是为什么上面的 cmdline 必须用 console=hvc0 的原因。

随机数生成器 (rng)

  • src: “/dev/urandom”:

    虚拟机配置了 Virtio RNG 设备,透传宿主机的 /dev/urandom。这对于 MicroVM 来说很重要,可以加速虚拟机启动(避免因为熵不足导致启动阻塞)。

注意事项:

  1. 路径依赖风险:这个 config.json 文件对宿主机的文件路径(Kernel 和 Disk)有强依赖。如果在本地测试备份/恢复没问题。如果要在不同机器间迁移快照,需要在恢复前修改这个 json 文件里的路径,或者确保两台机器目录结构一致。

  2. 嵌套虚拟化:

    默认开启了 nested: true,这会增加一些 CPU 开销,如果不需要在 VM 里跑 VM,建议启动时去掉相关参数以提升性能。

    关闭的方法:在启动时配置 cpu为 nested off,例如 --cpus boot=1,nested=off \

state.json

state.json 文件大小约为 42 KB。

在 Cloud Hypervisor 的快照体系中,state.json 与 config.json 扮演着完全不同但互补的角色。

如果说 config.json 是虚拟机的**“骨架”(硬件配置),那么 state.json 就是虚拟机的“灵魂”**(运行时的瞬间状态)。

存放的信息

文件记录了虚拟机在暂停那一瞬间,所有“非静态”的、动态变化的数据。具体包括:

  • vCPU 寄存器状态:这是最核心的部分。包含:
    • 通用寄存器:RAX, RBX, RSP (栈指针), RIP (指令指针 - 代码执行到哪一行了)。
    • 控制寄存器:CR0, CR3 (页表地址), CR4 等。
    • 段寄存器:CS, DS, SS 等。
    • 浮点数与向量寄存器:用于数学计算的状态。
    • 简单说:它记录了 CPU 下一条指令要算什么,以及当前的计算结果存在哪。
  • 设备后端状态 (Virtio Devices):
    • Virtio Queues (虚拟队列):记录了磁盘或网卡读写到哪一个位置了(Available Ring 和 Used Ring 的索引)。
    • Feature Bits:宿主机和虚拟机协商好了开启哪些功能(比如是否开启了巨型帧、多队列等)。
  • 中断控制器状态 (vPIC / vIOAPIC / LAPIC):
    • 记录当前有哪些中断正在排队等待 CPU 处理,哪些中断被屏蔽了。
  • 时钟与计时器:
    • 虚拟机内部的时间偏移量,确保恢复后时间能尽量同步。

用处

它的唯一作用就是“现场还原”。

当执行 resume 或从文件恢复虚拟机时:

  1. Cloud Hypervisor 先读取 config.json 创建出 CPU 线程和设备对象(造出机器)。
  2. 然后读取 memory 文件把 RAM 数据填回去(恢复记忆)。
  3. 最后读取 state.json,把每一个 CPU 寄存器的值填回去,把网卡/磁盘队列的指针拨回到原来的位置(恢复思维)。

如果没有 state.json,虚拟机虽然有内存数据,但 CPU 不知道该从内存的哪个地址开始执行指令,也不知道刚才磁盘读写到一半的数据该怎么处理,虚拟机就会立刻崩溃。

注意事项

  1. 绝对不要手动修改

    config.json 里的磁盘路径可以手动改(比如迁移机器后路径变了),但 state.json 里的数据是极度敏感的二进制状态的序列化。

    • 风险:改错一个标点或数字,CPU 恢复时的寄存器状态就会错乱,导致 Guest OS 报 Kernel Panic 或直接死机。
    • 建议:视其为只读的二进制文件。
  2. 版本强耦合 (Version Lock)

    Cloud Hypervisor 开发迭代很快,state.json 的内部结构(Schema)经常会变。

    • 风险:用 v50.0.0 生成的 state.json,很大可能无法在 v51.0.0 或 v52.0.0 上恢复。
    • 建议:生产环境中,快照恢复必须使用与创建快照时完全相同版本的 Cloud Hypervisor。
  3. 与内存文件的原子性

    state.json 和同目录下的内存文件(通常叫 memory)是即时对应的。

    在 Cloud Hypervisor 的快照体系中,state(或者您看到的 state.json)与 config.json 扮演着完全不同但互补的角色。

    如果说 config.json 是虚拟机的**“骨架”(硬件配置),那么 state.json 就是虚拟机的“灵魂”**(运行时的瞬间状态)。

  4. 包含敏感数据

    • 风险:由于它保存了 CPU 寄存器,如果快照时某个程序正在处理密码或私钥,这些明文密钥可能正躺在 state.json 的寄存器值里。
    • 建议:如果是在公有云或不可信环境传输快照,必须像保护磁盘文件一样保护 state.json。
  5. CPU 拓扑一致性

    state.json 里的 vCPU 数据列表是按照 config.json 里的 CPU 数量顺序排列的。恢复时,宿主机不仅要提供相同数量的 CPU,最好连 CPU 的型号特性(Host CPU Model)也尽量保持一致,否则可能出现指令集不兼容(比如快照时用到了 AVX512,恢复的机器不支持)。

memory-ranges

以 4g 内存规格的快照文件为例:

$ ls -lh
total 4.1G
-rw------- 1 root root 1.4K Dec 30 19:13 config.json
-rw------- 1 root root 4.0G Dec 30 19:13 memory-ranges
-rw------- 1 root root  35K Dec 30 19:13 state.json

可以使用支持稀疏文件的 tar -S 命令来将这个稀疏文件打包并使用 zstd 压缩:

sudo tar -cvSf snapshot.tar.zstd -I 'zstd -T0' config.json memory-ranges state.json

打包出来的 snapshot.tar.zstd 文件只有区区 67M,非常的小:

ls -lh
total 4.1G
-rw------- 1 root root 1.4K Dec 30 19:13 config.json
-rw------- 1 root root 4.0G Dec 30 19:13 memory-ranges
-rw-rw-r-- 1 sky  sky   67M Jan  4 15:39 snapshot.tar.zstd
-rw------- 1 root root  35K Dec 30 19:13 state.json

复制这个文件到其他目录,然后以支持稀疏文件的 tar 命令进行解压缩:

mkdir snapshot-4g-distributed
cd snapshot-4g-distributed
cp ../snapshot-4g/snapshot.tar.zstd .

sudo tar -xvSf snapshot.tar.zstd -I 'zstd -d'

解压缩之后的目录文件为:

ls -lh 
total 4.1G
-rw------- 1 root root 1.4K Dec 30 19:13 config.json
-rw------- 1 root root 4.0G Dec 30 19:13 memory-ranges
-rw-rw-r-- 1 sky  sky   67M Jan  4 15:44 snapshot.tar.zstd
-rw------- 1 root root  35K Dec 30 19:13 state.json

memory-ranges 文件解压缩之后恢复到 4.0G 的表面大小。为了验证这个 memory-ranges 文件依然是稀疏文件,我们再次用 tar 命令进行打包压缩测试:

sudo tar -cvSf snapshot2.tar.zstd -I 'zstd -T0' config.json memory-ranges state.json

重新打包的 snapshot2.tar.zstd 文件依然是 67M,验证前面对稀疏文件的打包/传输/解包过程都是支持稀疏文件的。

ls -lh                                                                              
total 4.2G
-rw------- 1 root root 1.4K Dec 30 19:13 config.json
-rw------- 1 root root 4.0G Dec 30 19:13 memory-ranges
-rw-r--r-- 1 root root  67M Jan  4 15:48 snapshot2.tar.zstd
-rw-rw-r-- 1 sky  sky   67M Jan  4 15:44 snapshot.tar.zstd
-rw------- 1 root root  35K Dec 30 19:13 state.json

因此,对于快照文件的存储和传输,使用支持稀疏文件的打包压缩方式是必须的,可以极大的减少存储和网络传输的流量压力,以及下载快照文件带来的延迟。

重复这个测试,对其他内存规格的快照文件进行打包和压缩:

1.3 - 优化性能

cloud hypervisor 快照优化性能

准备工作

准备目录和文件

继续使用之前的 work/test/cloudhypervisor 目录:

cd /home/sky/work/test/cloudhypervisor

启动

冷启动虚拟机,用于制作快照,注意修改内容大小设置:

sudo /home/sky/work/soft/cloudhypervisor/bin/cloud-hypervisor \
    --api-socket /home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock \
    --cpus boot=1,nested=off \
    --memory size=512M \
    --kernel /home/sky/work/test/cloudhypervisor/vmlinux.bin \
    --cmdline "root=/dev/vda1 rw quiet 8250.nr_uarts=0" \
    --disk path=/home/sky/work/test/cloudhypervisor/ubuntu-cloud-image/rootfs.raw \
    --console off \
    --serial off \
    --log-file /dev/null

制作快照

根据前面设置的内存大小,制作快照,保存在不同的目录下,备用:

rm -rf /home/sky/work/test/cloudhypervisor/snapshot-4g
mkdir -p /home/sky/work/test/cloudhypervisor/snapshot-4g
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock pause
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  snapshot file:///home/sky/work/test/cloudhypervisor/snapshot-4g
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  resume
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  shutdown
sudo fuser -k -TERM /home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock

重复以上操作,可以分别制作出 512M/1G/2G/4G 的快照文件,用于后面的恢复操作。

恢复虚拟机

执行恢复虚拟机的命令,注意选择快照文件的来源目录,其实就是选择不同的内存规格:

sudo /home/sky/work/soft/cloudhypervisor/bin/cloud-hypervisor \
    --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock \
    --restore source_url=file:///home/sky/work/test/cloudhypervisor/snapshot-4g

恢复之后,虚拟机是处于 pause 状态的,因此还要执行 resume 才能唤醒到正常运行状态:

sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  resume

恢复性能测试

默认

使用脚本 test_restore_speed.sh 进行测试,执行前修改脚本中的这一行,指定要使用的不同内存规格的快照文件:

SNAPSHOT_URL="file:///home/sky/work/test/cloudhypervisor/snapshot-512m"

执行前强制清理 page cache:

./test_restore_speed.sh false

多次测试的结果汇总为:

====== 开始性能测试 (Cache: false Size=4G) ======

 1. Load (Disk -> RAM)     :   1913.322 ms
 2. Resume (CPU Active)    :     16.584 ms
 --------------------------------------------------
 3. Total Recovery         :   1929.907 ms

====== 开始性能测试 (Cache: false Size=2G) ======

 1. Load (Disk -> RAM)     :    985.878 ms
 2. Resume (CPU Active)    :     14.172 ms
 --------------------------------------------------
 3. Total Recovery         :   1000.050 ms

====== 开始性能测试 (Cache: false Size=1G) ======

 1. Load (Disk -> RAM)     :    533.121 ms
 2. Resume (CPU Active)    :     15.142 ms
 --------------------------------------------------
 3. Total Recovery         :    548.263 ms

====== 开始性能测试 (Cache: false Size=512M) ======

 1. Load (Disk -> RAM)     :    304.199 ms
 2. Resume (CPU Active)    :     15.110 ms
 --------------------------------------------------
 3. Total Recovery         :    319.310 ms

page cache优化

类似的,不过执行前执行 page cache 优化:

./test_restore_speed.sh true
====== 开始性能测试 (Cache: true Size=4G) ======

 1. Load (Disk -> RAM)     :    623.998 ms
 2. Resume (CPU Active)    :     14.062 ms
 --------------------------------------------------
 3. Total Recovery         :    638.060 ms

====== 开始性能测试 (Cache: true Size=2G) ======

 1. Load (Disk -> RAM)     :    333.440 ms
 2. Resume (CPU Active)    :     17.197 ms
 --------------------------------------------------
 3. Total Recovery         :    350.637 ms

====== 开始性能测试 (Cache: true Size=1G) ======

 1. Load (Disk -> RAM)     :    190.534 ms
 2. Resume (CPU Active)    :     16.542 ms
 --------------------------------------------------
 3. Total Recovery         :    207.076 ms

====== 开始性能测试 (Cache: true Size=512M ======

 1. Load (Disk -> RAM)     :    105.908 ms
 2. Resume (CPU Active)    :     16.547 ms
 --------------------------------------------------
 3. Total Recovery         :    122.456 ms

HugePages 优化

类似,但是在启动虚拟机时设置内存为 hugepages=on:

sudo /home/sky/work/soft/cloudhypervisor/bin/cloud-hypervisor \
    --api-socket /home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock \
    --cpus boot=1,nested=off \
    --memory size=1G,hugepages=on \
    --kernel /home/sky/work/test/cloudhypervisor/vmlinux.bin \
    --cmdline "root=/dev/vda1 rw quiet 8250.nr_uarts=0" \
    --disk path=/home/sky/work/test/cloudhypervisor/ubuntu-cloud-image/rootfs.raw \
    --console off \
    --serial off \
    --log-file /dev/null

同样制作快照,为了和之前 hugepages=off 的快照区分,存放在不同的目录,以后缀 -hugepage 为标志:

rm -rf /home/sky/work/test/cloudhypervisor/snapshot-1g-hugepage
mkdir -p /home/sky/work/test/cloudhypervisor/snapshot-1g-hugepage
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock pause
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  snapshot file:///home/sky/work/test/cloudhypervisor/snapshot-1g-hugepage
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  resume
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock  shutdown
sudo fuser -k -TERM /home/sky/work/test/cloudhypervisor/cloud-hypervisor.sock

继续测试,开启 hugepage + 不开启 page cache 基本没差别:

====== 开始性能测试 (Cache: false Size=4G) ======

 1. Load (Disk -> RAM)     :   1906.534 ms
 2. Resume (CPU Active)    :     15.309 ms
 --------------------------------------------------
 3. Total Recovery         :   1921.843 ms

====== 开始性能测试 (Cache: false Size=2G) ======

 1. Load (Disk -> RAM)     :    985.883 ms
 2. Resume (CPU Active)    :     13.876 ms
 --------------------------------------------------
 3. Total Recovery         :    999.759 ms

====== 开始性能测试 (Cache: false Size=1G) ======

 1. Load (Disk -> RAM)     :    521.281 ms
 2. Resume (CPU Active)    :     14.697 ms
 --------------------------------------------------
 3. Total Recovery         :    535.978 ms

====== 开始性能测试 (Cache: false Size=512M) ======

 1. Load (Disk -> RAM)     :    300.310 ms
 2. Resume (CPU Active)    :     15.617 ms
 --------------------------------------------------
 3. Total Recovery         :    315.927 ms

开启 hugepage + 开启 page cache 能快一点:

====== 开始性能测试 (Cache: true Size=4G) ======

 1. Load (Disk -> RAM)     :    526.327 ms
 2. Resume (CPU Active)    :     15.826 ms
 --------------------------------------------------
 3. Total Recovery         :    542.153 ms

====== 开始性能测试 (Cache: true Size=2G) ======

 1. Load (Disk -> RAM)     :    312.838 ms
 2. Resume (CPU Active)    :     15.331 ms
 --------------------------------------------------
 3. Total Recovery         :    328.169 ms

====== 开始性能测试 (Cache: true Size=1G) ======

 1. Load (Disk -> RAM)     :    153.869 ms
 2. Resume (CPU Active)    :     16.558 ms
 --------------------------------------------------
 3. Total Recovery         :    170.427 ms

====== 开始性能测试 (Cache: true Size=512M ======

 1. Load (Disk -> RAM)     :    102.818 ms
 2. Resume (CPU Active)    :     15.310 ms
 --------------------------------------------------
 3. Total Recovery         :    118.128 ms

性能对比分析

将上面测试的几组数据汇总,对比一下:

内存规格 操作 默认(强制清理page cache) 开启 page cache 不开启 page cache + 开启 hugepage 开启 page cache + 开启 hugepage
4G restore 1913.322 ms 623.998 ms 1906.534 ms 526.327 ms
resume 16.584 ms 14.062 ms 15.309 ms 15.826 ms
total 1929.907 ms 638.060 ms 1921.843 ms 542.153 ms
2G restore 985.878 ms 333.440 ms 985.883 ms 312.838 ms
resume 14.172 ms 17.197 ms 13.876 ms 15.331 ms
total 1000.050 ms 350.637 ms 999.759 ms 328.169 ms
1G restore 533.121 ms 190.534 ms 521.281 ms 153.869 ms
resume 15.142 ms 16.542 ms 14.697 ms 16.558 ms
total 548.263 ms 207.076 ms 535.978 ms 170.427 ms
512M restore 304.199 ms 105.908 ms 300.310 ms 102.818 ms
resume 15.110 ms 16.547 ms 15.617 ms 15.310 ms
total 319.310 ms 122.456 ms 315.927 ms 118.128 ms

分析:

  1. resume 操作的时间非常固定,稳定在 15 毫秒左右,不受内存规格和各种优化策略的影响
  2. restore 操作和内存规格影响非常大,基本呈现线性
  3. 开启 page cache 能极大的加速 restore 的速度,但也只能加速到 30% 左右,不能直接到非常小,而且也是和内存规格直接相关(几乎也是线性)
  4. 开启 hugepage 能再次加速 restore 的速度,但很有限。

结论:

  1. restore 操作的确是在读取和操作完整的内存快照文件,并没有跳过空闲内存

1.4 - 延迟加载

cloud hypervisor 实现延迟加载的快照方式

2 - 文件后端内存

cloud hypervisor 的文件后端内存

2.1 - 介绍

cloud hypervisor 的文件后端内存介绍

在 Cloud Hypervisor (CH) 中,使用文件作为内存后端(File-backed memory)主要是为了实现高性能(Hugepages)、内存共享(vhost-user)或持久化内存(PMEM)等功能。

这个配置主要通过 --memory 参数下的 file 选项来实现。

基本语法

核心参数是 –memory:

--memory size=<内存大小>,file=<文件路径>[,shared=on|off][,hugepages=on|off]
  • size: 虚拟机内存大小 (例如 1G, 4G).
  • file: 主机(Host)上用于映射内存的文件的绝对路径。
  • shared: (可选) 是否将内存映射为共享(MAP_SHARED)。如果需要与 vhost-user 设备通信,必须设为 on。
  • hugepages: (可选) 显式声明该文件位于 Hugepages 文件系统中。

常见使用场景

使用 Hugepages (大页内存)

这是最常见的用途,推荐用于生产环境。

使用大页内存可以减少 TLB miss,显著提高虚拟机性能。

步骤:

  1. 确保主机已挂载 hugetlbfs (通常在 /dev/hugepages)。
  2. 指定文件路径

命令示例:

# 准备目录
mkdir -p /home/sky/work/test/cloudhypervisor/file-backed-memory
cd /home/sky/work/test/cloudhypervisor/file-backed-memory

sudo rm -rf /home/sky/work/test/cloudhypervisor/file-backed-memory/cloud-hypervisor.sock
sudo /home/sky/work/soft/cloudhypervisor/bin/cloud-hypervisor \
    --api-socket /home/sky/work/test/cloudhypervisor/file-backed-memory/cloud-hypervisor.sock \
    --cpus boot=2 \
    --memory size=4G,file=/dev/hugepages/ch-ram-backing \
    --kernel /home/sky/work/test/cloudhypervisor/vmlinux.bin \
    --cmdline "root=/dev/vda1 console=hvc0 rw" \
    --disk path=/home/sky/work/test/cloudhypervisor/ubuntu-cloud-image/rootfs.raw


# 完成后关闭
sudo /home/sky/work/soft/cloudhypervisor/bin/ch-remote --api-socket=/home/sky/work/test/cloudhypervisor/file-backed-memory/cloud-hypervisor.sock shutdown

注意: Cloud Hypervisor 会在 /dev/hugepages/ 下创建名为 ch-ram-backing 的文件。如果该路径是 hugetlbfs 挂载点,CH 会自动识别并使用大页。

3 - unikernel

cloud hypervisor unikernel

3.1 - Running Nanos Unikernels under Cloud Hypervisor

youtube上的介绍视频

Running Nanos Unikernels under Cloud Hypervisor

https://www.youtube.com/watch?v=1IteC54pcWM


这是一份为您详细整理的视频内容图文解析。由于我无法直接生成视频截图文件,我将采用**“关键画面描述与终端代码块还原”**的方式来为您展示“图片”和视觉信息,结合详细的文字解析,带您完整回顾该视频。


📑 视频内容摘要 (Summary)

本视频是一个关于 Cloud Hypervisor 与 Nanos Unikernel (单内核) 结合使用的硬核技术演示。 作者首先介绍了 Cloud Hypervisor 的官方网站、核心特性(如基于 Rust 开发、毫秒级启动、极小内存开销等)以及其背后的支持大厂(包含腾讯云等)。随后,作者转入 Linux 终端实战,展示了一个简单的 Go 语言程序,将其编译为 Nanos Unikernel 镜像,并通过 Cloud Hypervisor 极速拉起该轻量级虚拟机。程序成功在虚拟机内运行并输出日志。最后,作者通过强杀进程结束了演示,并总结指出这种极速、轻量的技术栈非常适合用来构建 Serverless(无服务器)架构。


🎬 详细内容与图文解析 (Detailed Breakdown)

第一阶段:介绍 Cloud Hypervisor (00:00 - 00:27)

  • 📺 画面展示: 浏览器停留在 Cloud Hypervisor 的官方网站主页 (cloudhypervisor.org)。

    [网页视觉呈现] 大标题:Run Cloud Virtual Machines Securely and Efficiently (安全高效地运行云虚拟机) 简介:Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) implemented in Rust… 核心特性面板:Secure (安全)、Fast (快,启动<100ms)、Slim (轻量)、Kata Containers (支持 Kata)、Live migration (热迁移) 等。 支持机构:Alibaba, AMD, ARM, ByteDance, Intel, Microsoft, Tencent Cloud。

  • 📝 文字解说: 作者欢迎大家来到视频教程系列。今天的主角是 Cloud Hypervisor。他介绍道,这是一个用 Rust 语言编写的全新虚拟机监视器(VMM)。它拥有许多酷炫的功能,并且得到了如阿里巴巴、字节跳动、英特尔、腾讯、Ampere 等众多大厂的支持。作者预告,今天的演示目标是在 Cloud Hypervisor 上启动一些 Unikernel(单内核)。

第二阶段:准备 Go 语言测试程序 (00:27 - 00:50)

  • 📺 画面展示: 画面切换到纯黑背景的 Linux 终端。作者使用 Vim 打开了一个名为 main.go 的文件。

    [终端代码截图还原]

    package main
    import (
        "fmt"
        "time"
    )
    func main() {
        for i := 0; i < 10; i++ {
            fmt.Println("hello from nanos")
            time.Sleep(1 * time.Second)
        }
    }
    
  • 📝 文字解说: 作者展示了他准备好的一个非常简单的 Go 语言程序。这个程序的功能只有一个:通过一个 for 循环,每隔 1 秒钟在控制台打印一次 "hello from nanos",总共循环 10 次。作者表示,他在此之前已经提前将这个 Go 程序编译好了。

第三阶段:查看编译产物与 Nanos 内核 (00:50 - 01:36)

  • 📺 画面展示: 终端执行了 ls -lh 命令,展示当前目录下的文件列表和大小。

    [终端输出截图还原]

    cyberg@nanos:~/...$ ls -lh
    -rwxrwxr-x 1 cyberg cyberg 4.0M May 24 08:15 cloud-hypervisor
    -rw-rw-r-- 1 cyberg cyberg 2.4M May 24 08:27 kernel.img
    -rwxrwxr-x 1 cyberg cyberg 120  May 24 08:30 run.sh
    
  • 📝 文字解说: 作者向大家展示当前工作目录中的三个关键文件:

    1. cloud-hypervisor:编译好的 VMM 执行文件,体积非常小巧,大约只有 4MB。
    2. kernel.img:这是 Nanos Unikernel 的内核镜像文件。
    3. 为了照顾想要自己从源码编译 Nanos 的开发者,作者还特意敲击路径,展示了这个 kernel.img 在 Nanos 源码树中的默认生成位置(通常在 .../nanos/output/platform/pc/bin/kernel.img)。

第四阶段:一键极速启动轻量虚拟机 (01:36 - 02:18)

  • 📺 画面展示: 作者查看并执行了启动脚本 run.sh。随后,终端立刻开始疯狂输出虚拟机的启动日志和 Go 程序的运行结果。

    [启动脚本与运行画面还原]

    # 查看 run.sh 内容
    cyberg@nanos:~/...$ cat run.sh
    ./cloud-hypervisor --kernel kernel.img --disk "path=/home/cyberg/ch/g" --console off --serial tty
    
    # 执行脚本
    cyberg@nanos:~/...$ sudo ./run.sh
    [sudo] password for cyberg: ******
    
    # 虚拟机瞬间拉起并输出
    en1: assigned FE80::2C2C:47FF:FEE6:7D07
    hello from nanos
    hello from nanos
    hello from nanos
    ...
    
  • 📝 文字解说: 作者打开了 run.sh 脚本,讲解了启动 Cloud Hypervisor 的核心参数:指定内核文件 (--kernel)、指定挂载的磁盘路径 (--disk) 以及将输出重定向到串口终端 (--serial tty)。 当他输入 sudo 密码按下回车后,虚拟机在瞬间(毫秒级)就完成了启动。我们直接在屏幕上看到了网卡分配的日志,紧接着,刚才编写的 Go 程序开始正常工作,屏幕上稳稳地每秒打印出一句 "hello from nanos"。

第五阶段:展示进程管理并结束演示 (02:18 - 02:44)

  • 📺 画面展示: 作者将终端分屏(Split Screen)。左侧继续打印日志,右侧用于查找并杀掉进程。

    [分屏操作画面还原]

    # 右侧终端操作
    cyberg@nanos:~/...$ ps aux | grep cloud
    root     13904  0.0  0.0 2004488 64536 pts/2 ... ./cloud-hypervisor --kernel ...
    cyberg@nanos:~/...$ sudo kill -9 13904
    
    # 左侧终端显示:
    hello from nanos
    hello from nanos
    Killed
    cyberg@nanos:~/...$
    
  • 📝 文字解说: 作者提到,Cloud Hypervisor 其实还提供了一个非常强大的 API(REST API),可以通过 API 来控制虚拟机的生命周期,但他今天不打算演示,留到以后的视频再说。 为了结束当前一直打印的虚拟机,他在右侧终端使用 ps aux 找到了 Cloud Hypervisor 的进程 PID,然后直接运行 sudo kill -9 强杀了该进程。左侧的虚拟机随即停止运行,显示 Killed 并退回了宿主机的终端提示符。 最后,作者总结道:“这就是在 Cloud Hypervisor 下运行 Nanos Unikernel 的演示。我认为你可以利用这项技术制作出非常酷炫的 Serverless(无服务器)风格的特性。下次再见!”