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.
283 lines
11 KiB
Markdown
283 lines
11 KiB
Markdown
# 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.
|