Zyvor Janus is a discrete-event simulator for Kubernetes-native GPU scheduling inspired by Zyvor Forge. It models clusters, MIG, topology, tenants, quotas, gang scheduling, and AI workloads, enabling scheduler development, RL research, and performance evaluation without requiring physical NVIDIA GPUs.
▶ Watch the demo — Forge (production GPU/Kubernetes control plane) and Zyvor Janus (its simulator) running side by side, ~3 min.
- No GPUs required — full discrete-event simulation of cluster placement, MIG slicing, NVLink/PCIe topology penalties, and gang scheduling
- Forge-native — imports real
FabricAIJob/FabricGPUNode/FabricQuotaCRDs and replays production scheduler traces for oracle-vs-live diffing - Pluggable schedulers —
fifo,priority,preemptive,bestfit, and Forge's own policy, swappable with one CLI flag - RL-ready — Gymnasium environment + PPO baseline for scheduler policy research
- Full observability stack — Rich terminal dashboard, Next.js web UI (runs, benchmark, what-if), and an OpenAI-compatible inference shim for calibrated LLM serving metrics
- Architecture
- Installation
- Quick start
- Project layout
- Milestones
- Dual-node "migrate" demo
- Forge input
- Enterprise & support
- License
- Rust core — event engine, cluster model, schedulers, metrics, Forge bundle loader, inference timing model
- Python API — PyO3 bindings, Forge CRD adapters, Gymnasium env, visualization, FastAPI server, AIPerf adapters
- Web UI — Next.js dashboard (runs, benchmark, what-if) + Rich CLI live dashboard
Pre-built images are published to GitHub Container Registry on every release:
docker pull ghcr.io/hypersdk/zyvor-janus-api:latest
docker pull ghcr.io/hypersdk/zyvor-janus-web:latest
# Run the API + web dashboard locally:
docker network create zyvor-janus 2>/dev/null || true
docker run -d --name zyvor-janus-api --network zyvor-janus -p 8080:8080 \
ghcr.io/hypersdk/zyvor-janus-api:latest
docker run -d --name zyvor-janus-web --network zyvor-janus -p 3000:3000 \
-e ZYVOR_JANUS_API_URL=http://zyvor-janus-api:8080 \
ghcr.io/hypersdk/zyvor-janus-web:latestThen open http://localhost:3000 (default login Admin / Admin@321 — override via
ZYVOR_JANUS_DASHBOARD_USER / ZYVOR_JANUS_DASHBOARD_PASSWORD env vars on the web container).
Pin a specific release instead of latest with ghcr.io/hypersdk/zyvor-janus-api:vX.Y.Z.
cd deploy/kubernetes
cp secret.example.yaml secret.yaml # edit credentials
kubectl apply -f secret.yaml
kubectl apply -k .See deploy/kubernetes/README.md for the full guide
(local kind/minikube cluster, Ingress, remote k3s deploy via
scripts/deploy-remote.sh).
git clone https://github.com/hypersdk/zyvor-janus.git
cd zyvor-janus
cargo build --release -p zyvor-janus-cli
# Optional: Python bindings + web API (builds the PyO3 extension)
./scripts/setup_dev.sh
source .venv/bin/activate
pip install -e '.[server]' # FastAPI / uvicorn (web API)See CONTRIBUTING.md for the full dev setup, including
optional viz, rl, and dashboard extras.
cargo run -p zyvor-janus-cli -- run --config configs/clusters/small_h100.yamlThat's it — a full cluster simulation with no GPU, no Kubernetes, no config beyond the one YAML file. Everything below is one cargo run (or script) away; click a row to expand it.
▸ Forge export bundle — test Forge without GPUs (M2)
- Export from a Forge cluster:
mkdir -p forge-export/{jobs,cluster,quotas}
kubectl get fabricaijobs -A -o yaml > forge-export/jobs/all.yaml
kubectl get fabricgpunodes -o yaml > forge-export/cluster/nodes.yaml
kubectl get fabricquotas -A -o yaml > forge-export/quotas/all.yaml-
Add calibrated runtime profiles in
configs/profiles/(seeconfigs/profiles/gpt-13b.yaml). -
Run simulation:
cargo run -p zyvor-janus-cli -- run \
--forge-bundle forge-export \
--profiles-dir configs/profilesOr use the included fixture:
cargo run -p zyvor-janus-cli -- run \
--forge-bundle tests/fixtures/forge \
--profiles-dir configs/profiles▸ Scheduler policies — fifo · priority · preemptive · bestfit · forge (M6)
# Priority: highest priority first, no preemption
cargo run -p zyvor-janus-cli -- run --config configs/clusters/priority_scheduler.yaml
# Preemptive: evict lower-priority running jobs for higher-priority arrivals
cargo run -p zyvor-janus-cli -- run --config configs/clusters/preemption_preemptive.yaml
# Forge bundle with scheduler flag (fifo | priority | preemptive | forge | bestfit)
cargo run -p zyvor-janus-cli -- run \
--forge-bundle tests/fixtures/forge \
--scheduler forge▸ Scheduler trace replay — compare vs production Forge (M3)
cargo run -p zyvor-janus-cli -- replay \
--trace tests/fixtures/traces/fifo_match.jsonl \
--config configs/clusters/single_gpu.yamlWrites outputs/trace_diff.json with oracle vs FIFO placement diffs.
▸ MIG simulation — fractional GPU slices (M4)
cargo run -p zyvor-janus-cli -- run --config configs/clusters/mig_single.yamlMIG jobs use mig_profile and mig_count (Forge spec.mig) to allocate fractional GPU slices with a simulated reconfiguration delay.
▸ Topology + gang placement — NVLink domains, gang scheduling (M5/M6)
# NVLink-domain-aware placement; cross-domain jobs inflate runtime
cargo run -p zyvor-janus-cli -- run --config configs/clusters/topology_penalty.yaml
# Gang jobs require GPUs spread across gang_size_nodes distinct nodes
cargo run -p zyvor-janus-cli -- run --config configs/clusters/gang_m6.yaml
# Gang timeout fails jobs that cannot be placed in time (jobs_failed metric)
cargo run -p zyvor-janus-cli -- run --config configs/clusters/gang_timeout_m6.yaml▸ Inference + LLM serving metrics — TTFT/TPS estimation (P1)
cargo run -p zyvor-janus-cli -- run \
--config configs/clusters/inference_llama.yaml \
--output outputs/inference_metrics.jsonUses profile v2 fields (prefill_ms_per_token, decode_tps) to estimate TTFT/TPS. See docs/benchmark_platform.md.
▸ Visualization — job timeline plots (M8)
cargo run -p zyvor-janus-cli -- run \
--config configs/clusters/small_h100.yaml \
--jobs-output outputs/jobs.json
pip install -e '.[viz]'
python python/examples/plot_run.py outputs/jobs.json▸ Live CLI dashboard — Rich terminal UI (Phase 1)
See docs/ui_dashboard.md for full setup, scripts, and troubleshooting.
./scripts/setup_dev.sh
./scripts/run_live_dashboard.sh --config configs/clusters/small_h100.yaml▸ Web dashboard — FastAPI + Next.js, runs/benchmark/what-if (Phase 2)
See docs/ui_dashboard.md for API reference and scripts.
./scripts/setup_dev.sh
cd web && npm install && cd ..
./scripts/run_web_dashboard.sh # http://localhost:3000Routes: / (runs + compare), /benchmark, /what-if, /login. Or run API and UI separately: ./scripts/run_web_api.sh · ./scripts/run_web_ui.sh
▸ Deploy — Docker / Kubernetes
./deploy/build-images.sh
kubectl apply -k deploy/kubernetes▸ Python + RL — Gymnasium env + PPO baseline (M7)
On macOS Homebrew Python, use the setup script if venv fails on pyexpat:
./scripts/setup_dev.sh
source .venv/bin/activate
pip install -e '.[rl]'
python python/examples/run_rl_env.py
python python/baselines/ppo_cleanrl.py --config configs/clusters/rl_small.yaml▸ AIPerf calibration — import real benchmark results (P7)
PYTHONPATH=python python -m zyvor_janus.benchmarks.aiperf_adapter \
import tests/fixtures/aiperf/sample_result.json --profile llama-70b▸ OpenAI-compatible shim — drop-in /v1/chat/completions (P6)
With the web API running (./scripts/run_web_api.sh):
curl -s http://127.0.0.1:8080/v1/chat/completions \
-H "Authorization: Bearer dev-zyvor-janus-key" \
-H "Content-Type: application/json" \
-d '{"model":"llama-70b","messages":[{"role":"user","content":"hi"}],"stream":false}'See docs/openai_shim.md.
▸ Test layout — what's covered, how to run it
| Layer | Location | What it covers |
|---|---|---|
| Rust unit | crates/*/src/ (#[test] modules) |
Models, MIG, resource manager, FIFO, trace parsing |
| Rust integration | crates/zyvor-janus-config/tests/integration.rs |
Full sim pipelines (YAML, Forge bundle, trace, MIG, RL, topology) |
| CLI integration | crates/zyvor-janus-cli/tests/cli_integration.rs |
zyvor-janus run / replay binary |
| Python unit | python/tests/test_unit_adapters.py |
CRD mapping, profiles, bundle, trace adapters |
| Python integration | python/tests/test_integration_cli.py |
CLI via cargo run -p zyvor-janus-cli |
| Benchmark / UI | python/tests/test_*benchmark*, test_server_*, test_openai_* |
API, shim, AIPerf, score |
cargo test --workspace --exclude zyvor-janus-py
cargo test -p zyvor-janus-config --test integration
cargo test -p zyvor-janus-cli --test cli_integration
PYTHONPATH=python python3 -m unittest discover -s python/tests -v
bash benchmarks/ci/run_golden.shcrates/ Rust workspace (core, scheduler, config, metrics, cli, py)
python/zyvor_janus/ Adapters, envs, viz, dashboard, server, benchmarks, workloads
web/ Next.js web dashboard (/ , /benchmark, /what-if)
scripts/ setup_dev.sh, run_*_dashboard.sh, clean.sh
deploy/ Docker images + Kubernetes manifests
benchmarks/ci/ Golden sim regression script
configs/
profiles/ Calibrated model runtimes (v1 + inference v2)
clusters/ Cluster + workload YAML examples
analytics/ Cost model (score weights optional)
tests/fixtures/ Forge, traces, AIPerf, benchmark goldens
docs/ Architecture, milestones, UI, benchmark platform, deploy
See docs/milestones.md. M1–M8 complete, including topology runtime inflation, gang timeout, RL (M7), and visualization (M8).
Benchmark platform (MVP shipped): docs/benchmark_platform.md — inference model, serving traces, score vector, /benchmark + /what-if UI, OpenAI shim, AIPerf adapter, twin store API, CI golden script. Remaining gaps (full sim-vs-measured UI, CLI --serving-trace, twin library page) are listed in that doc and the manual test guide.
Schedulers: fifo, priority, preemptive, forge (alias for preemptive), bestfit.
Preemptive scheduler moves a low-priority job across machines after preemption:
cargo run -p zyvor-janus-cli -- run --config configs/clusters/dual_node_preempt.yaml
# Dashboard + wow reel (writes ~/Desktop/zyvor-janus-client-dual-node-migrate-wow-reel.mp4)
./scripts/run_web_dashboard.sh # separate terminal
ZYVOR_JANUS_DEMO_CONFIG=dual_node_preempt.yaml \
node scripts/demo-videos/record-zyvor-janus-2gpu-migrate-wow-reel.mjsThis is a digital-twin placement migrate. Forge's production live migrate is KubeVirt VMs (Path A); pod checkpoint/restore is experimental Path B — see Forge docs/product/POD_VS_VM_MIGRATION.md.
See docs/forge_input.md for CRD mapping rules, export workflow, and adapter levels.
Zyvor Janus is the free digital-twin simulator for Zyvor Forge, the production GPU/Kubernetes control plane. Janus lets you develop and validate scheduling policy entirely offline; Forge is what runs it against real GPUs.
| Zyvor Janus (this repo) | Zyvor Forge (zyvor.dev/forge) | |
|---|---|---|
| What it is | Discrete-event simulator / digital twin | Production GPU/Kubernetes control plane |
| GPUs required | None — fully simulated | Real GPU fleet |
| Use case | Scheduler R&D, RL research, capacity planning, CI regression gates | Live cluster scheduling, MIG/topology-aware placement, gang scheduling in production |
| Input | Forge CRD export bundles, YAML configs, trace replay | Live cluster via FabricAIJob / FabricGPUNode / FabricQuota CRDs |
| Support | GitHub Issues | SLA, onboarding, migration support — zyvor.dev/contact |
Looking for enterprise support, managed deployments, or the full Forge platform? Visit zyvor.dev.
This repository is licensed under the Apache License, Version 2.0. You may use, modify, and run it for personal, lab, and commercial production use at no charge, subject to Apache-2.0 (preserve notices / NOTICE where required).
Production support, SLAs, and Zyvor Enterprise products are licensed separately. Contact sales@zyvor.dev or see zyvor.dev.
