docs: client-perf analysis, bench harness and work journal

Everything the next agent needs to run the Phase 2 optimisation loop on a
machine that can launch the client:

- analysis/client-perf/: LEVERS (ranked levers + corrections), BENCH-MATRIX
  (world, scenes, config IDs, blocks B0-B14 with decision rules),
  PLAYER-TUNING, SPAWN-TUNING, research briefs, the jar scanner and its
  output, observed default configs, and proposed-configs/ (build.py
  generates tiers and bench variants and fails on unknown keys;
  apply_variant.py applies a variant and merges options.txt).
- analysis/client-perf/bench/onion-bench/: bench-world datapack (scene
  teleports, Create grid, mob pen, sound storm, 120 s teleport tour).
- analysis/audit/: the static recipe/dependency audit, including gen_fixes.py,
  which generates the shipped Paxi datapack and was never tracked.
- phase0/: per-machine measurement harness (Steam Deck, 7700K/1060,
  6700K/1080 Ti).
- .pi/journal.md: running work log; read it first.

All of it is packwizignored, so nothing here ships to players.
This commit is contained in:
logan committed 2026-10-14 18:15:32 -04:00
1 parent d80f85b3f6
commit 611a1a5952
102 files changed
+25853

No files matched your search

+282
View File
@@ -0,0 +1,282 @@
# Phase 0 — P2: i7-6700K / GTX 1080 Ti (Linux, Docker present)
Setup and measurement procedure for the CPU-and-RAM-bound machine in the Onion MC client
tuning fleet.
---
## Profile
| | |
| --- | --- |
| CPU | Intel i7-6700K, 4 cores / 8 threads, 4.0 GHz base / 4.2 GHz turbo (Skylake) |
| GPU | NVIDIA GTX 1080 Ti, **11 GB VRAM** (Pascal) |
| RAM | 16 GB total, **~8 GB occupied by Docker** |
| OS | Linux |
| **Binding constraint** | **CPU (main thread) + RAM/GC pressure** |
| **What this tier tests** | CPU-render and RAM/GC ladder steps on a capable GPU |
| **Expected DH answer** | **On, with the CPU/thread preset lowered — quality preset stays up** |
### The important inversion
This machine's GPU is the second-strongest in the fleet by a wide margin, and 11 GB of VRAM
is more than most current mid-range cards. **DH's GPU cost is not the problem here.** The
constraints are a 4C/8T Skylake main thread and a heap that has to fit in roughly 8 GB.
Consequence: for this tier, **turn DH's CPU/thread preset down, not its quality preset.**
That is the opposite lever from the other two machines, and it is the clearest example of
why the ladder cannot be a single global ordering.
### Standing constraint for this machine
> **Do not alter Docker or any other running process for the sake of these measurements.**
> Assume the existing load is constant and consistent, and treat it as a fixed property of
> this test rig.
That changes the guardrail from *"abort if RAM is low"* to *"record the baseline and verify
it stayed constant."* See Step 3 and Step 9.
---
## Shared measurement protocol
Applies to every machine in the fleet. Duplicated here so this document stands alone.
1. **Uncapped, vsync off** during measurement. Apply the FPS cap only *after* tuning.
2. **Metric is p99 frametime and 1% low, not average FPS.**
3. **Discard 10–15 s of warmup** per scene — JIT, chunk load, initial GC.
4. **Settle after any render-distance or DH change.**
5. **Three runs per configuration, report median and spread.**
6. **One variable per run.**
7. Guardrails: FPS limiter active, governor moved, or RAM headroom shifted materially →
the run is invalid.
---
## Step 1 — Preconditions
- [ ] Confirm the **proprietary NVIDIA driver** is in use. `nouveau` would invalidate both
the performance and the measurements.
```bash
nvidia-smi # must succeed
glxinfo -B | grep -E 'OpenGL renderer|OpenGL version'
```
- [ ] Confirm the compositor is not forcing vsync. If on X11/KDE, disable compositing for
the measurement session; on Wayland, disable any tearing/queueing control.
- [ ] Confirm the display resolution and refresh rate, and record them. Resolution is a
bigger GPU lever than most mod settings.
## Step 2 — GPU power state and throttling
Do this before every session. A GPU that is power-capped or thermally throttled produces
numbers that look like mod effects.
```bash
# Prefer maximum performance instead of adaptive clocks
nvidia-settings -a '[gpu:0]/GPUPowerMizerMode=1'
# Check for throttle reasons — SW Power Cap / HW Slowdown must be absent
nvidia-smi -q -d PERFORMANCE
```
Start background logging of VRAM, clocks, power and temperature. **Use this exact command
on the Windows machine too** — identical tooling on both NVIDIA boxes:
```bash
mkdir -p ~/mcbench/logs
nvidia-smi --query-gpu=timestamp,memory.used,clocks.sm,clocks.mem,power.draw,temperature.gpu,utilization.gpu \
--format=csv -l 1 > ~/mcbench/logs/gpu-$(date +%F-%H%M%S).csv &
```
`memory.used` is your VRAM series. On this machine it should stay comfortable; it is the
control against the 6 GB machine.
## Step 3 — Establish the noise floor (do this first)
Because Docker's load is assumed constant rather than eliminated, **you must measure the
noise before you can interpret any delta.** Otherwise you cannot tell a real 3% mod effect
from Docker doing something.
- [ ] Run the **same configuration, same scene, three times**, with no changes at all.
- [ ] Record p50/p95/p99 spread across those three runs.
- [ ] **That spread is your detection threshold.** Any later measurement smaller than this
spread is not evidence.
If the spread is large, Docker's activity is the first suspect. Record it as a known
limitation of this rig rather than trying to fix it.
## Step 4 — Record the RAM baseline
Do not change the running load — measure and freeze it.
```bash
free -h
cat /proc/meminfo | grep -E 'MemAvailable|SwapTotal|SwapFree'
```
- [ ] Record `MemAvailable` at session start.
- [ ] Repeat the reading before and after each block of runs. **If it drifts materially,
Docker's footprint changed and the runs are not comparable.** That is the check that
makes the "constant load" assumption falsifiable instead of merely asserted.
- [ ] Confirm no swap is being touched during runs:
```bash
grep -E 'pswpin|pswpout' /proc/vmstat # before and after; both should not move
```
Swapping during a run invalidates the p99 frametime numbers outright.
## Step 5 — CPU governor
The governor is a system setting, not a running process, and pinning it removes DVFS noise
on a 4C/8T Skylake. This is the one system-level change recommended on this machine.
```bash
sudo cpupower frequency-set -g performance
# or:
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
```
- [ ] Record the governor value before and after, and keep it identical across sessions.
- [ ] Revert to your normal governor when the measurement work is done.
> Also worth noting for the tier guide, independent of this benchmarking: a mild overclock
> on this CPU is a larger and cheaper win than most mod tuning. Measure at stock first so
> the baseline is comparable.
## Step 6 — MangoHud
```bash
sudo pacman -S --needed mangohud # or your distro's package
```
Config lives at `~/.config/MangoHud/MangoHud.conf`. Start from the packaged example
(`pacman -Ql mangohud | grep MangoHud.conf` to locate it) rather than a transcription, then
set:
```ini
output_folder=/home/<user>/mcbench/logs
autostart_log=1
log_duration=30
fps_limit=0
frametime=1
frame_timing=1
# percentiles — confirm the exact key/syntax in the packaged example
```
## Step 7 — Launcher and JVM
Use **Prism Launcher** (or ATLauncher) and launch from a terminal so the environment is
under your control.
**Java:** 21 — **the same JVM build as the other two machines**, to avoid a confound.
**Wrapper command** — Prism → *Edit Instance → Settings → Custom Commands → Wrapper
command*:
```
mangohud
```
Fallback if it fails to hook: `mangohud --dlsym`.
**JVM arguments** (identical across the fleet except `-Xmx`):
```
-Xmx6G
-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC
-XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M
-XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4
-XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90
-XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32
-XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1
```
**Heap sizing rule for this machine:** `-Xmx` = min(6 GB, `MemAvailable` − 2 GB). With
~8 GB available that lands at 6 G; if the baseline reading is lower, lower the heap.
**Omit `-XX:+AlwaysPreTouch` on this machine.** It commits the entire heap up front, which
is exactly the wrong thing when Docker already holds half the RAM.
> **Read this before interpreting GC results.** Because heap is capped by Docker's
> footprint, GC pressure on this rig will be **higher than on an otherwise identical
> machine without Docker running.** This rig is therefore expected to *over-weight* the
> RAM/GC ladder steps and to show worse p99 lows than the same hardware would in the wild.
> Record it as a property of the rig; do not attribute it to a mod.
## Step 8 — Pin the in-game settings
Controlled variables — set once, record, do not change between runs unless the run is
testing that setting.
- Graphics: Fancy
- Render distance: 8
- Particles: All
- Clouds: Fancy
- Entity shadows: On
- Biome blend: fixed, recorded
- Mipmap levels: 4
- GUI scale: fixed number
- **Max framerate: Unlimited**
- **VSync: Off**
- FOV, resolution, fullscreen mode: fixed and recorded
## Step 9 — Verification run
- [ ] Launch, confirm the MangoHud overlay appears over Minecraft.
- [ ] Confirm a CSV lands in `~/mcbench/logs` with a frametime column.
- [ ] Confirm `nvidia-smi` logging is producing a CSV.
- [ ] Run the Step 3 noise-floor test and record the spread.
- [ ] Confirm `MemAvailable` and swap counters are stable across the three runs.
## Step 10 — Per-session checklist
- [ ] `nvidia-smi` works; power mizer set to max performance; no throttle reasons
- [ ] `nvidia-smi` background logging started
- [ ] Governor recorded (and pinned to `performance` if using that policy)
- [ ] `MemAvailable` recorded; swap counters checked
- [ ] Compositor vsync disabled
- [ ] MangoHud overlay visible, CSV output folder writable
- [ ] Noise floor re-established if the session is a new day
## Step 11 — Recording sheet
| Field | Example |
| --- | --- |
| Date / session | 2026-09-28-a |
| Machine | P2-6700K-1080Ti |
| Config ID | baseline / dh-cpu-preset-low / emf-off / … |
| Scene | A-base / B-terrain / C-gui |
| Run # | 1 / 2 / 3 |
| CSV file | |
| p50 / p95 / p99 frametime (ms) | |
| 1% low FPS | |
| Avg FPS | |
| VRAM peak (MB) | |
| Throttle flag | none / SW Power Cap / HW Slowdown |
| `MemAvailable` before / after | |
| Swap delta | must be 0 |
| Notes | |
---
## Machine-specific caveats
- **Docker is not removed, so RAM is a live variable that must be monitored, not assumed
away.** The Step 4 before/after check is what keeps the results honest.
- **This rig will over-weight RAM/GC ladder steps** relative to identical hardware without
Docker. Documented, not corrected.
- **Establish the noise floor before interpreting anything.** With a constant-but-unknown
background load, small deltas are unreadable until you know the spread.
- **CPU is the bottleneck, so CPU-side ladder steps are expected to show their largest
deltas here** — EMF/ETF and Fresh Animations, DH's thread preset, Sound Physics reverb,
LambDynamicLights. GPU-side steps may show almost nothing, and that is a real result, not
a failed measurement.
- **Pascal is a legacy driver branch.** Verify the driver is still current before drawing
comparisons against newer hardware.
- **11 GB VRAM means this is the fleet's control for "VRAM is not the constraint."**
Comparing this machine against the 6 GB GTX 1060 isolates GPU/VRAM effects, because both
machines share the same 4C/8T CPU class. If a knob you classified as CPU-render diverges
between the two, your classification is wrong — that is the taxonomy self-check.