diff options
Diffstat (limited to 'docs/PERFORMANCE.md')
| -rw-r--r-- | docs/PERFORMANCE.md | 103 |
1 files changed, 0 insertions, 103 deletions
diff --git a/docs/PERFORMANCE.md b/docs/PERFORMANCE.md deleted file mode 100644 index 6ba8d1b..0000000 --- a/docs/PERFORMANCE.md +++ /dev/null @@ -1,103 +0,0 @@ -# Open-IOV Performance Testing & A/B Methodology - -> **Status: superseded (historical).** Part of the pre-2026-09-23 docs; kept -> as a record. Current entry point: [docs/README.md](README.md). Performance -> replacement: -> [05-operations/01-performance-correctness-security.md](05-operations/01-performance-correctness-security.md). - -> How we measure vGPU performance against bare metal, interpret the results, -> and keep overhead on the critical path honest. **Run correctness first** -> (`docs/DEBUGGING.md` §5) — numbers from a half-working stack are noise. - ---- - -## 1. What overhead is acceptable (targets) - -| Path | Target | Why | -|------|--------|-----| -| GSP RPC round-trip (doorbell→response→MSI-X) | < 50 µs (stretch: < 10 µs) | every driver op goes through here | -| MSI-X injection (eventfd → guest handler) | < 5 µs | completion latency dominates | -| Guest BAR0 MMIO read/write | < 2 µs (shadow RAM) | hot path for register polling | -| CUDA kernel launch (added overhead vs bare metal) | < 10% | user-visible | -| Memory alloc/map RPCs | < 100 µs | setup-time, amortized | -| CUDA compute throughput | ≥ 95% of bare metal | GPU-bound, should be ~free | -| Graphics (frame rate) | ≥ 90% of bare metal | swapchain + submission overhead | - -## 2. The A/B rule - -Every measurement runs **twice on the same machine, same boot if possible**: - -- **A (bare metal)**: workload on the physical GPU via the host's stock - driver (or our OpenRM nvidia.ko directly on the hardware). -- **B (vGPU)**: identical workload in the guest on the emulated vGPU. - -Same binary, same input sizes, same environment (governor, clocks, hugepages). -Report **B/A ratio %** — never absolute numbers alone. - -One variable at a time. If B regresses, you changed the stack, the workload, -or the machine — find which before optimizing. - -## 3. Microbenchmarks (build these first) - -1. **RPC round-trip**: from the guest, submit a DEBUG/NOOP-ish RPC in a loop; - time doorbell-write → response-visible. Host side: `gsp_emu_get_stats()` - gives `total_latency_ns` and counts — divide for per-RPC host cost. - (Add `trace_printk` in `gsp_emu_dispatch_rpc` entry/exit for distribution; - read via `/sys/kernel/debug/tracing/trace`.) -2. **MSI-X latency**: timestamp (guest TSC) at RPC submit → in the guest - driver's interrupt handler. Compare with the host eventfd_signal timestamp. -3. **BAR0 shadow read latency**: guest loops reading a shadow register; - expect ~memory speed (uncached, so ~100-300 ns) — anything ≥ 1 µs means - you're trapping somewhere you shouldn't. -4. **Doorbell polling cost**: host `top`/`perf` on `gsp_emu_N` — the adaptive - poll (busy → 50-100 µs sleep) should sit at ~0% CPU when idle, and react - within one sleep quantum under load. Tune `GSP_EMU_POLL_*` only with data. - -## 4. Workload benchmarks - -Runner: `tools/benchmark_infrastructure.sh` (extend it; keep the A/B pattern). -In-guest execution goes through the harness (`vgpu_vm.py exec`) or the guest -test agent (`tools/guest_agent/`). - -| Suite | What | Pass criterion | -|-------|------|----------------| -| `cuda-samples vectorAdd` | smoke + element-wise throughput | correct result; ≥ 95% B/A | -| `simpleCUBLAS` | SGEMM TFLOPS | ≥ 95% B/A | -| `nvbandwidth` (if available) | H2D/D2H/device copy GB/s | report; DMA path validation | -| `glxgears -info` / a real GL app | frame rate | ≥ 90% B/A | -| `nvenc`/`nvdec` sample | transcode fps | functional (perf later) | -| PyTorch CUDA op (matmul loop) | end-to-end framework | ≥ 90% B/A | - -Always log: guest/host driver versions, GPU clocks (`nvidia-smi -q -d CLOCK` -both sides — throttling skews everything), and the command lines. - -## 5. Where the overhead lives (profile in this order) - -1. **RPC dispatch** — the single biggest lever. Everything the guest driver - does funnels through the emulation thread. -2. **Doorbell polling cadence** — too slow = latency; too hot = host CPU burn. -3. **eventfd/MSI-X delivery** — measure, don't assume. -4. **BAR0 uncached semantics** — shadow is UC for the guest; that's - MMIO-correct but slow for large reads. If the driver bulk-reads shadow, - consider caching-safe sub-regions. -5. **Memory model gap** (ALLOC host-pages vs BAR1 direct VRAM) — see - `docs/GSP_EMULATION_ARCHITECTURE.md` §3. Until unified, DMA-heavy - workloads are not representative. - -## 6. Optimizing safely - -- Change one thing, re-run the A/B pair, keep the numbers with the commit. -- Never optimize off bare-metal-only data: the goal is B/A, not A. -- If a change makes B faster but breaks the §5 validation checklist in - `docs/DEBUGGING.md`, it doesn't count. -- Record results in `STATE.md` (date, versions, B/A ratios) so regressions - are visible across commits. - -## 7. Reporting template - -``` -Date / commit / versions (guest=host=firmware=emulation): -Machine / GPU / clocks locked?: -Test, unit, A (bare), B (vGPU), B/A %: -Notes (what changed vs last run): -``` |
