Volt VMM (Neutron Stardust): source-available under AGPSL v5.0
KVM-based microVMM for the Volt platform: - Sub-second VM boot times - Minimal memory footprint - Landlock LSM + seccomp security - Virtio device support - Custom kernel management Copyright (c) Armored Gates LLC. All rights reserved. Licensed under AGPSL v5.0
This commit is contained in:
270
docs/benchmark-volt.md
Normal file
270
docs/benchmark-volt.md
Normal file
@@ -0,0 +1,270 @@
|
||||
# Volt VMM Benchmark Results
|
||||
|
||||
**Date:** 2026-03-08
|
||||
**Version:** Volt v0.1.0
|
||||
**Host:** Intel Xeon Silver 4210R @ 2.40GHz (2 sockets × 10 cores, 40 threads)
|
||||
**Host Kernel:** Linux 6.1.0-42-amd64 (Debian)
|
||||
**Methodology:** 10 iterations per test, measuring wall-clock time from process start to kernel panic (no rootfs). Kernel: Linux 4.14.174 (vmlinux ELF format).
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Binary size | 3.10 MB (3,258,448 bytes) |
|
||||
| Binary size (stripped) | 3.10 MB (3,258,440 bytes) |
|
||||
| Cold boot to kernel panic (median) | 1,723 ms |
|
||||
| VMM init time (median) | 110 ms |
|
||||
| VMM init time (min) | 95 ms |
|
||||
| Memory overhead (RSS - guest) | ~6.6 MB |
|
||||
| Startup breakdown (first log → VM running) | 88.8 ms |
|
||||
| Kernel boot time (internal) | ~1.41 s |
|
||||
| Dynamic dependencies | libc, libm, libgcc_s |
|
||||
|
||||
---
|
||||
|
||||
## 1. Binary Size
|
||||
|
||||
| Metric | Size |
|
||||
|--------|------|
|
||||
| Release binary | 3,258,448 bytes (3.10 MB) |
|
||||
| Stripped binary | 3,258,440 bytes (3.10 MB) |
|
||||
| Format | ELF 64-bit LSB PIE executable, dynamically linked |
|
||||
|
||||
**Dynamic dependencies:**
|
||||
- `libc.so.6`
|
||||
- `libm.so.6`
|
||||
- `libgcc_s.so.1`
|
||||
- `linux-vdso.so.1`
|
||||
- `ld-linux-x86-64.so.2`
|
||||
|
||||
> Note: Binary is already stripped in release profile (only 8 bytes difference).
|
||||
|
||||
---
|
||||
|
||||
## 2. Cold Boot Time (Process Start → Kernel Panic)
|
||||
|
||||
Full end-to-end time from process launch to kernel panic detection. This includes VMM initialization, kernel loading, and the Linux kernel's full boot sequence (which ends with a panic because no rootfs is provided).
|
||||
|
||||
### vmlinux-4.14 (128M RAM)
|
||||
|
||||
| Iteration | Time (ms) |
|
||||
|-----------|-----------|
|
||||
| 1 | 1,750 |
|
||||
| 2 | 1,732 |
|
||||
| 3 | 1,699 |
|
||||
| 4 | 1,704 |
|
||||
| 5 | 1,730 |
|
||||
| 6 | 1,736 |
|
||||
| 7 | 1,717 |
|
||||
| 8 | 1,714 |
|
||||
| 9 | 1,747 |
|
||||
| 10 | 1,703 |
|
||||
|
||||
| Stat | Value |
|
||||
|------|-------|
|
||||
| **Minimum** | 1,699 ms |
|
||||
| **Maximum** | 1,750 ms |
|
||||
| **Median** | 1,723 ms |
|
||||
| **Average** | 1,723 ms |
|
||||
| **Spread** | 51 ms (2.9%) |
|
||||
|
||||
### vmlinux-firecracker-official (128M RAM)
|
||||
|
||||
Same kernel binary, different symlink path.
|
||||
|
||||
| Iteration | Time (ms) |
|
||||
|-----------|-----------|
|
||||
| 1 | 1,717 |
|
||||
| 2 | 1,707 |
|
||||
| 3 | 1,734 |
|
||||
| 4 | 1,736 |
|
||||
| 5 | 1,710 |
|
||||
| 6 | 1,720 |
|
||||
| 7 | 1,729 |
|
||||
| 8 | 1,742 |
|
||||
| 9 | 1,714 |
|
||||
| 10 | 1,726 |
|
||||
|
||||
| Stat | Value |
|
||||
|------|-------|
|
||||
| **Minimum** | 1,707 ms |
|
||||
| **Maximum** | 1,742 ms |
|
||||
| **Median** | 1,723 ms |
|
||||
| **Average** | 1,723 ms |
|
||||
|
||||
> Both kernel files are identical (21,441,304 bytes each). Results are consistent.
|
||||
|
||||
---
|
||||
|
||||
## 3. VMM Init Time (Process Start → "VM is running")
|
||||
|
||||
This measures only the VMM's own initialization overhead, before any guest code executes. Includes KVM setup, memory allocation, CPUID configuration, kernel loading, vCPU creation, and register setup.
|
||||
|
||||
| Iteration | Time (ms) |
|
||||
|-----------|-----------|
|
||||
| 1 | 100 |
|
||||
| 2 | 95 |
|
||||
| 3 | 112 |
|
||||
| 4 | 114 |
|
||||
| 5 | 121 |
|
||||
| 6 | 116 |
|
||||
| 7 | 105 |
|
||||
| 8 | 108 |
|
||||
| 9 | 99 |
|
||||
| 10 | 112 |
|
||||
|
||||
| Stat | Value |
|
||||
|------|-------|
|
||||
| **Minimum** | 95 ms |
|
||||
| **Maximum** | 121 ms |
|
||||
| **Median** | 110 ms |
|
||||
|
||||
> Note: Measurement uses `date +%s%N` and polling for "VM is running" in output, which adds ~5-10ms of polling overhead. True VMM init time from TRACE logs is ~89ms.
|
||||
|
||||
---
|
||||
|
||||
## 4. Startup Breakdown (TRACE-level Timing)
|
||||
|
||||
Detailed timing from TRACE-level logs, showing each VMM initialization phase:
|
||||
|
||||
| Δ from start (ms) | Phase |
|
||||
|---|---|
|
||||
| +0.000 | Program start (Volt VMM v0.1.0) |
|
||||
| +0.124 | KVM initialized (API v12, max 1024 vCPUs) |
|
||||
| +0.138 | Creating virtual machine |
|
||||
| +29.945 | CPUID configured (46 entries) |
|
||||
| +72.049 | Guest memory allocated (128 MB, anonymous mmap) |
|
||||
| +72.234 | VM created |
|
||||
| +72.255 | Loading kernel |
|
||||
| +88.276 | Kernel loaded (ELF vmlinux at 0x100000, entry 0x1000000) |
|
||||
| +88.284 | Serial console initialized (0x3f8) |
|
||||
| +88.288 | Creating vCPU |
|
||||
| +88.717 | vCPU 0 configured (64-bit long mode) |
|
||||
| +88.804 | Starting VM |
|
||||
| +88.814 | VM running |
|
||||
| +88.926 | vCPU 0 enters KVM_RUN |
|
||||
|
||||
### Phase Durations
|
||||
|
||||
| Phase | Duration (ms) | % of Total |
|
||||
|-------|--------------|------------|
|
||||
| Program init → KVM init | 0.1 | 0.1% |
|
||||
| KVM init → CPUID config | 29.8 | 33.5% |
|
||||
| CPUID config → Memory alloc | 42.1 | 47.4% |
|
||||
| Memory alloc → VM create | 0.2 | 0.2% |
|
||||
| Kernel loading | 16.0 | 18.0% |
|
||||
| Device init + vCPU setup | 0.6 | 0.7% |
|
||||
| **Total VMM init** | **88.9** | **100%** |
|
||||
|
||||
### Key Observations
|
||||
|
||||
1. **CPUID configuration takes ~30ms** — calls `KVM_GET_SUPPORTED_CPUID` and filters 46 entries
|
||||
2. **Memory allocation takes ~42ms** — `mmap` of 128MB anonymous memory + `KVM_SET_USER_MEMORY_REGION`
|
||||
3. **Kernel loading takes ~16ms** — parsing 21MB ELF binary + page table setup
|
||||
4. **vCPU setup is fast** — under 1ms including MSR configuration and register setup
|
||||
|
||||
---
|
||||
|
||||
## 5. Memory Overhead
|
||||
|
||||
Measured RSS 2 seconds after VM start (guest kernel booted and running).
|
||||
|
||||
| Guest Memory | RSS (kB) | VmSize (kB) | VmPeak (kB) | Overhead (kB) | Overhead (MB) |
|
||||
|-------------|----------|-------------|-------------|---------------|---------------|
|
||||
| 128 MB | 137,848 | 2,909,504 | 2,909,504 | 6,776 | 6.6 |
|
||||
| 256 MB | 268,900 | 3,040,576 | 3,106,100 | 6,756 | 6.6 |
|
||||
| 512 MB | 535,000 | 3,302,720 | 3,368,244 | 10,712 | 10.5 |
|
||||
| 1 GB | 1,055,244 | 3,827,008 | 3,892,532 | 6,668 | 6.5 |
|
||||
|
||||
**Overhead = RSS − Guest Memory Size**
|
||||
|
||||
| Stat | Value |
|
||||
|------|-------|
|
||||
| **Typical VMM overhead** | ~6.6 MB |
|
||||
| **Overhead components** | Binary code/data, KVM structures, kernel image in-memory, page tables, serial buffer |
|
||||
|
||||
> Note: The 512MB case shows slightly higher overhead (10.5 MB). This may be due to kernel memory allocation patterns or measurement timing. The consistent ~6.6 MB for 128M/256M/1G suggests the true VMM overhead is approximately **6.6 MB**.
|
||||
|
||||
---
|
||||
|
||||
## 6. Kernel Internal Boot Time
|
||||
|
||||
Time from first kernel log message to kernel panic (measured from kernel's own timestamps in serial output):
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| First kernel message | `[0.000000]` Linux version 4.14.174 |
|
||||
| Kernel panic | `[1.413470]` VFS: Unable to mount root fs |
|
||||
| **Kernel boot time** | **~1.41 seconds** |
|
||||
|
||||
This is the kernel's own view of boot time. The remaining ~0.3s of the 1.72s total is:
|
||||
- VMM init: ~89ms
|
||||
- Kernel rebooting after panic: ~1s (configured `panic=1`)
|
||||
- Process teardown: small
|
||||
|
||||
Actual cold boot to usable kernel: **~89ms (VMM) + ~1.41s (kernel) ≈ 1.5s total**.
|
||||
|
||||
---
|
||||
|
||||
## 7. CPUID Configuration
|
||||
|
||||
Volt configures 46 CPUID entries for the guest vCPU.
|
||||
|
||||
### Strategy
|
||||
- Starts from `KVM_GET_SUPPORTED_CPUID` (host capabilities)
|
||||
- Filters out features not suitable for guests:
|
||||
- **Removed from leaf 0x1 ECX:** DTES64, MONITOR/MWAIT, DS_CPL, VMX, SMX, EIST, TM2, PDCM
|
||||
- **Added to leaf 0x1 ECX:** HYPERVISOR bit (signals VM to guest)
|
||||
- **Removed from leaf 0x1 EDX:** MCE, MCA, ACPI thermal, HTT (single vCPU)
|
||||
- **Removed from leaf 0x7 EBX:** HLE, RTM (TSX), RDT_M, RDT_A, MPX
|
||||
- **Removed from leaf 0x7 ECX:** PKU, OSPKE, LA57
|
||||
- **Cleared leaves:** 0x6 (thermal), 0xA (perf monitoring)
|
||||
- **Preserved:** All SSE/AVX/AVX-512, AES, XSAVE, POPCNT, RDRAND, RDSEED, FSGSBASE, etc.
|
||||
|
||||
### Key CPUID Values (from TRACE)
|
||||
|
||||
| Leaf | Register | Value | Notes |
|
||||
|------|----------|-------|-------|
|
||||
| 0x0 | EAX | 22 | Max standard leaf |
|
||||
| 0x0 | EBX/EDX/ECX | GenuineIntel | Host vendor passthrough |
|
||||
| 0x1 | ECX | 0xf6fa3203 | SSE3, SSSE3, SSE4.1/4.2, AVX, AES, XSAVE, POPCNT, HYPERVISOR |
|
||||
| 0x1 | EDX | 0x0f8bbb7f | FPU, TSC, MSR, PAE, CX8, APIC, SEP, PGE, CMOV, PAT, CLFLUSH, MMX, FXSR, SSE, SSE2 |
|
||||
| 0x7 | EBX | 0xd19f27eb | FSGSBASE, BMI1, AVX2, SMEP, BMI2, ERMS, INVPCID, RDSEED, ADX, SMAP, CLFLUSHOPT, CLWB, AVX-512(F/DQ/CD/BW/VL) |
|
||||
| 0x7 | EDX | 0xac000400 | SPEC_CTRL, STIBP, ARCH_CAP, SSBD |
|
||||
| 0x80000001 | ECX | 0x00000121 | LAHF_LM, ABM, PREFETCHW |
|
||||
| 0x80000001 | EDX | — | SYSCALL ✓, NX ✓, LM ✓, RDTSCP, 1GB pages |
|
||||
| 0x40000000 | — | KVMKVMKVM | KVM hypervisor signature |
|
||||
|
||||
### Features Exposed to Guest
|
||||
- **Compute:** SSE through SSE4.2, AVX, AVX2, AVX-512 (F/DQ/CD/BW/VL/VNNI), FMA, AES-NI, SHA
|
||||
- **Memory:** SMEP, SMAP, CLFLUSHOPT, CLWB, INVPCID, PCID
|
||||
- **Security:** IBRS, IBPB, STIBP, SSBD, ARCH_CAPABILITIES, NX
|
||||
- **Misc:** RDRAND, RDSEED, XSAVE/XSAVEC/XSAVES, TSC (invariant), RDTSCP
|
||||
|
||||
---
|
||||
|
||||
## 8. Test Environment
|
||||
|
||||
| Component | Details |
|
||||
|-----------|---------|
|
||||
| Host CPU | Intel Xeon Silver 4210R @ 2.40GHz (Cascade Lake) |
|
||||
| Host RAM | Available (no contention during tests) |
|
||||
| Host OS | Debian, Linux 6.1.0-42-amd64 |
|
||||
| KVM | API version 12, max 1024 vCPUs |
|
||||
| Guest kernel | Linux 4.14.174 (vmlinux ELF, 21 MB) |
|
||||
| Guest config | 1 vCPU, variable RAM, no rootfs, `console=ttyS0 reboot=k panic=1 pci=off` |
|
||||
| Volt | v0.1.0, release build, dynamically linked |
|
||||
| Rust | nightly (cargo build --release) |
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
1. **Boot time is dominated by the kernel** (~1.41s kernel vs ~89ms VMM). VMM overhead is <6% of total boot time.
|
||||
2. **Memory overhead is minimal** at ~6.6 MB regardless of guest memory size.
|
||||
3. **Binary is already stripped** in release profile — `strip` saves only 8 bytes.
|
||||
4. **CPUID filtering is comprehensive** — removes dangerous features (VMX, TSX, MPX) while preserving compute-heavy features (AVX-512, AES-NI).
|
||||
5. **Hugepages not tested** — host has no hugepages allocated (`HugePages_Total=0`). The `--hugepages` flag is available but untestable.
|
||||
6. **Both kernels are identical** — `vmlinux-4.14` and `vmlinux-firecracker-official.bin` are the same file (same size, same boot times).
|
||||
Reference in New Issue
Block a user