# Performance Mode Benchmark Harness

This experimental harness compares the same scenario workloads across current prototype state
strategies:

- `full-snapshot-clone`
- `proxy-tracked-state`
- `manual-patch-baseline`
- `schema-generated-setter`

Documented raw-results command:

```sh
node experimental/performance-mode/benchmarks/run-benchmarks.js --format ndjson
```

Fast reproducibility command:

```sh
node experimental/performance-mode/benchmarks/run-benchmarks.js --quick --format ndjson
```

The output is newline-delimited JSON. The first row has `type: "machine"` with runtime and host
metadata. Each benchmark row has `type: "result"` with the strategy, scenario, raw timings, operation
counts, patch counts, rollback timing where applicable, and snapshot/patch byte counts.

This harness is intentionally not wired into `SimulationEngine`. It benchmarks the standalone
performance-mode prototype paths only.

## V0.3 Runtime Benchmark Harness

The V0.3 runtime benchmark slice compares the required workload classes across the required runtime
paths:

- `v0.2-single-bus`
- `v0.3-time-sliced-multi-bus`
- `worker-bus`

Workloads:

- `ball-pong-small-state`: the real `examples/performance-mode-ball-world/game.js` world-facade game,
  run headlessly through schema backend state and render mirror patches.
- `pacman-medium-state`: the real `experimental/performance-mode/games/pacman-world.js` world-facade
  Pac-Man module, initialized directly into gameplay so the benchmark exercises its schema and step path.
- `synthetic-many-entities-state`: many schema rows with moderate movement.
- `mostly-idle-many-entities-state`: many schema rows with sparse changes.
- `all-entities-changing-worst-case`: many schema rows where every entity changes each tick.

The worker-bus row is currently an explicit deferred record per workload: the generic worker-bus runtime
exists elsewhere in the repo, but this deterministic CLI comparison does not yet wire a worker-backed
benchmark path.

Human-readable table plus machine-readable JSON:

```sh
node experimental/performance-mode/benchmarks/run-v03-runtime-benchmarks.js --quick
```

Machine-readable JSON only:

```sh
node experimental/performance-mode/benchmarks/run-v03-runtime-benchmarks.js --quick --json
```

Longer deterministic local run:

```sh
node experimental/performance-mode/benchmarks/run-v03-runtime-benchmarks.js --ticks 128 --both
```

Each JSON result record includes:

- `path`
- `workload`
- `status`
- `ticks`
- `workloadTargetTicks`
- `workTicks`
- `elapsedMs`
- `avgTickMs`
- `maxTickMs`
- `avgRenderMs`
- `maxRenderMs`
- `rollbackMs`
- `catchUpMs`
- `mirrorPatchGenerationMs`
- `snapshotMs`
- `hashMs`
- `workerPostMessageMs`
- `workerPostMessageStatus`
- `memoryGrowthBytes`
- `messageCount`
- `rollbackCount`
- `catchUpEvents`
- `sourceSwitchCount`
- snapshot/patch byte counts

For comparable records, `ticks` and `workloadTargetTicks` name the same workload target. Extra replay
work is reported separately as `workTicks`, so a time-sliced multi-bus run can show additional catch-up
work without pretending it ran a different target workload.

Rollback cost is measured by running a real backend rollback after each ok path reaches the target
tick. Non-worker paths report `workerPostMessageMs: null` with `workerPostMessageStatus:
"not-applicable"` instead of a numeric placeholder. Deferred worker rows report unexecuted timing,
count, and byte metrics as `null`; they must not use synthetic zeroes for work that never ran.
Worker rows must report measured metrics once the worker benchmark path is implemented, or an
explicit deferred status while that path is not yet part of this CLI harness.

Worker-bus gap: until a deterministic worker-backed benchmark path is added, the `worker-bus` record
must remain `status: "deferred"` with a `deferredReason`; this is a blocker for claiming full matrix
coverage, but not for verifying the harness output shape.
