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:
1 parent
d80f85b3f6
commit
611a1a5952
102 files changed
+25853
No files matched your search
@@ -0,0 +1,249 @@
|
||||
# Phase 0 — P0: Steam Deck
|
||||
|
||||
Setup and measurement procedure for the lowest-end test machine in the Onion MC client
|
||||
tuning fleet.
|
||||
|
||||
---
|
||||
|
||||
## Profile
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| CPU | AMD Zen 2, 4 cores / 8 threads, 2.4–3.5 GHz |
|
||||
| GPU | AMD RDNA2 (Van Gogh), 8 CU, integrated |
|
||||
| RAM | 16 GB LPDDR5, **shared with the GPU** |
|
||||
| Display | 1280×800 — LCD is 60 Hz, OLED is 90 Hz |
|
||||
| OS | SteamOS (Arch-based, read-only rootfs) |
|
||||
| **Binding constraint** | GPU compute, memory bandwidth, shared memory pressure |
|
||||
| **What this tier tests** | The floor. If the ladder holds here it holds anywhere. |
|
||||
| **Expected DH answer** | Off, or the minimum viable preset |
|
||||
|
||||
### Determine your panel
|
||||
|
||||
The LCD panel is 60 Hz. **If this is an LCD Deck, targets of 120 and 144 are meaningless
|
||||
on this machine** — it can only validate the 30 and 60 rows of the ladder. Record which
|
||||
panel you have; it changes what this machine can prove.
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
With a cap or vsync active, every configuration "hits" the target and the ladder never
|
||||
fires.
|
||||
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.** Both trigger rebuilds; measuring
|
||||
immediately measures the rebuild, not the steady state.
|
||||
5. **Three runs per configuration, report the median and the spread.** A single run of
|
||||
anything is noise.
|
||||
6. **One variable per run.** If you change two things, you have learned nothing.
|
||||
7. Guardrails: if the FPS limiter is active, the governor moved, or RAM headroom changed
|
||||
materially, the run is invalid — discard rather than interpret.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Preconditions
|
||||
|
||||
- [ ] Plugged into the charger. Battery vs. AC changes APU power behaviour.
|
||||
- [ ] Switch to **Desktop Mode**. All measurement happens here, launching Prism from a
|
||||
terminal. Gaming Mode routes the overlay through MangoApp, which cannot log.
|
||||
- [ ] Instance installed on **internal storage**, not a microSD card. Card I/O affects
|
||||
chunk loading and DH LOD reads.
|
||||
- [ ] Confirm panel refresh rate and record it.
|
||||
|
||||
## Step 2 — Disable the competing overlay
|
||||
|
||||
SteamOS's built-in performance overlay is **MangoApp**, not MangoHud. It is an IPC bridge
|
||||
and **cannot write CSV logs**. Running it alongside MangoHud produces two stacked overlays
|
||||
and aborts logging.
|
||||
|
||||
- [ ] Quick Access Menu (`...`) → **Performance**
|
||||
- [ ] **Performance Overlay Level → 0**
|
||||
- [ ] **Framerate Limit → Off** (critical — otherwise every config "hits" the cap)
|
||||
- [ ] **TDP Limit → Off**, or pin it to a fixed value (e.g. 15 W) and never change it
|
||||
between sessions. Whichever you choose, record it and keep it constant.
|
||||
- [ ] Check that no per-game profile is re-enabling any of the above.
|
||||
- [ ] If Decky Loader is installed, disable any MangoHud/benchmark plugin that routes
|
||||
through MangoApp.
|
||||
|
||||
## Step 3 — CPU governor and thermals
|
||||
|
||||
The Deck's governor is normally `schedutil`. Two options:
|
||||
|
||||
- **Recommended:** leave it as SteamOS sets it, but *record* it
|
||||
(`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor`) and keep it identical
|
||||
across every session.
|
||||
- Pinning `performance` gives more consistent clocks but increases heat on a handheld,
|
||||
which risks thermal throttling — usually a worse trade for repeatability.
|
||||
|
||||
**Thermal soak:** let the Deck play for ~5 minutes before the first measured run. A cold
|
||||
Deck boosts then throttles; the first runs of a session are not representative. This is the
|
||||
single biggest source of bogus deltas on this machine.
|
||||
|
||||
## Step 4 — Install MangoHud
|
||||
|
||||
SteamOS's rootfs is read-only, and anything installed via `pacman` can be removed by a
|
||||
SteamOS update. Re-check this before every session.
|
||||
|
||||
```bash
|
||||
sudo steamos-readonly disable
|
||||
sudo pacman -S --needed mangohud
|
||||
sudo steamos-readonly enable
|
||||
```
|
||||
|
||||
Then find the actual paths — **do not assume them**:
|
||||
|
||||
```bash
|
||||
pacman -Ql mangohud | grep -E 'mangohud$|libMangoHud'
|
||||
```
|
||||
|
||||
This tells you the wrapper binary and the shared library path. Note them; you will need
|
||||
them if the wrapper route fails.
|
||||
|
||||
> **Alternative if you don't want to touch the rootfs:** MangoHudPy is built for
|
||||
> SteamOS/Bazzite and manages MangoHud configs and log uploads. Verify it can write CSV
|
||||
> logs before relying on it — some SteamOS MangoHud tooling routes through the MangoApp
|
||||
> IPC shim, which explicitly cannot write logs.
|
||||
|
||||
## Step 5 — MangoHud configuration
|
||||
|
||||
Generate the config from the packaged example rather than trusting a transcription:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/MangoHud ~/mcbench/logs
|
||||
cp /usr/share/doc/mangohud/MangoHud.conf ~/.config/MangoHud/MangoHud.conf # verify path with pacman -Ql
|
||||
```
|
||||
|
||||
Then set these keys in `~/.config/MangoHud/MangoHud.conf`:
|
||||
|
||||
```ini
|
||||
output_folder=/home/deck/mcbench/logs # required for logging
|
||||
autostart_log=1 # start logging automatically
|
||||
log_duration=30 # seconds; match your scene length
|
||||
fps_limit=0 # uncapped
|
||||
frametime=1
|
||||
frame_timing=1
|
||||
# percentiles: see the packaged example for the exact key/syntax — it defines a
|
||||
# '+'-separated list of percentiles emitted in the benchmark summary
|
||||
```
|
||||
|
||||
Confirm the exact percentile key name against the packaged example file. Logging can also
|
||||
be toggled at runtime (`toggle_logging`, default `Shift_L+F2`).
|
||||
|
||||
## Step 6 — Launcher and JVM
|
||||
|
||||
Use **Prism Launcher** (or ATLauncher) with the pack imported, then launch it from a
|
||||
terminal in Desktop Mode so the environment is under your control.
|
||||
|
||||
**Java:** 21 (Arch `jre21-openjdk` or Temurin 21). Use the **same JVM build across all
|
||||
three machines** where possible — different JVM builds are a confound.
|
||||
|
||||
**Wrapper command** — Prism → *Edit Instance → Settings → Custom Commands → Wrapper
|
||||
command*. This is the most reliable way to hook the Java process directly:
|
||||
|
||||
```
|
||||
mangohud
|
||||
```
|
||||
|
||||
If no overlay appears, or Minecraft fails to start, try:
|
||||
|
||||
```
|
||||
mangohud --dlsym
|
||||
```
|
||||
|
||||
**JVM arguments** (held identical across all three machines; only `-Xmx` differs):
|
||||
|
||||
```
|
||||
-Xmx5G
|
||||
-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
|
||||
```
|
||||
|
||||
**On `-Xmx5G`:** the Deck's 16 GB is shared with the GPU, so heap is not free. Start at
|
||||
5 G, never exceed 6 G, and treat the final value as a Phase 0 *output* derived from GC
|
||||
data, not a guess. Omit `-XX:+AlwaysPreTouch` here — committing the whole heap up front
|
||||
costs memory you may not have.
|
||||
|
||||
## Step 7 — Pin the in-game settings
|
||||
|
||||
These are **controlled variables**. Set them once, record them, and do not change them
|
||||
between runs unless the run is specifically testing that setting.
|
||||
|
||||
- Graphics: Fancy
|
||||
- Render distance: 8 (matches the server's `view-distance`)
|
||||
- Particles: All
|
||||
- Clouds: Fancy
|
||||
- Entity shadows: On
|
||||
- Biome blend: fixed value, recorded
|
||||
- Mipmap levels: 4
|
||||
- GUI scale: fixed number (not Auto)
|
||||
- **Max framerate: Unlimited**
|
||||
- **VSync: Off**
|
||||
- FOV, resolution, fullscreen mode: fixed and recorded
|
||||
|
||||
## Step 8 — Verification run
|
||||
|
||||
Prove the harness works before collecting any real data.
|
||||
|
||||
- [ ] Launch the pack from Prism with the wrapper command set.
|
||||
- [ ] Confirm the MangoHud overlay appears over Minecraft.
|
||||
- [ ] Load the benchmark scene, play 30 s.
|
||||
- [ ] Confirm a CSV file appeared in `~/mcbench/logs`.
|
||||
- [ ] Open the CSV and confirm it contains a frametime column.
|
||||
- [ ] Run the same configuration three times and check the spread. **If the spread is
|
||||
large, nothing downstream is trustworthy** — fix that before continuing.
|
||||
|
||||
## Step 9 — Per-session checklist
|
||||
|
||||
- [ ] Charger connected
|
||||
- [ ] Desktop Mode
|
||||
- [ ] SteamOS overlay level 0, FPS limit off, TDP as recorded
|
||||
- [ ] Governor matches previous sessions
|
||||
- [ ] MangoHud still installed (SteamOS update may have removed it)
|
||||
- [ ] 5-minute thermal soak completed
|
||||
- [ ] CSV output folder writable
|
||||
|
||||
## Step 10 — Recording sheet
|
||||
|
||||
Log one row per run:
|
||||
|
||||
| Field | Example |
|
||||
| --- | --- |
|
||||
| Date / session | 2026-09-28-a |
|
||||
| Machine | P0-SteamDeck-LCD |
|
||||
| Config ID | baseline / dh-off / emf-off / … |
|
||||
| Scene | A-base / B-terrain / C-gui |
|
||||
| Run # | 1 / 2 / 3 |
|
||||
| CSV file | `Minecraft_2026-09-28_14-22-01.csv` |
|
||||
| p50 / p95 / p99 frametime (ms) | |
|
||||
| 1% low FPS | |
|
||||
| Avg FPS | |
|
||||
| Peak measured frametime (ms) | |
|
||||
| Notes | e.g. "thermals settled", "DH disabled" |
|
||||
|
||||
---
|
||||
|
||||
## Machine-specific caveats
|
||||
|
||||
- **The overlay trap.** SteamOS gives you MangoApp, which looks like MangoHud and cannot
|
||||
write logs. Getting CSV requires launching through the MangoHud wrapper, in Desktop
|
||||
Mode, not through Gaming Mode.
|
||||
- **VRAM is not measurable here.** The GPU shares system memory, so there is no separate
|
||||
VRAM number to track. Watch total system RAM and swap instead; memory pressure is what
|
||||
you will actually see.
|
||||
- **SteamOS updates remove `pacman`-installed packages.** Verify MangoHud exists at the
|
||||
start of every session.
|
||||
- **60 Hz panel (LCD) cannot validate 120/144 targets.** Document this rather than
|
||||
pretending those rows are tested.
|
||||
- **Smallest thermal envelope of the fleet.** The warm-up soak is not optional.
|
||||
- **Per-core performance is much lower than the other two machines** despite the identical
|
||||
4C/8T topology. Do not assume a CPU-side result from P1/P2 transfers here at the same
|
||||
magnitude — only the direction should be expected to match.
|
||||
@@ -0,0 +1,243 @@
|
||||
# Phase 0 — P1: i7-7700K / GTX 1060 6 GB (Windows)
|
||||
|
||||
Setup and measurement procedure for the VRAM-bound machine in the Onion MC client tuning
|
||||
fleet.
|
||||
|
||||
---
|
||||
|
||||
## Profile
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| CPU | Intel i7-7700K, 4 cores / 8 threads, 4.2 GHz base (Kaby Lake) |
|
||||
| GPU | NVIDIA GTX 1060, **6 GB VRAM** (Pascal, GP106) |
|
||||
| RAM | 32 GB — **not a constraint on this machine** |
|
||||
| OS | **Windows** (the fleet's only Windows box) |
|
||||
| **Binding constraint** | **VRAM** |
|
||||
| **What this tier tests** | GPU/VRAM ladder steps with CPU and RAM held non-binding |
|
||||
| **Expected DH answer** | **On, with quality/distance reduced — VRAM is the wall** |
|
||||
|
||||
### Why this machine matters
|
||||
|
||||
- **32 GB of RAM removes RAM/GC as a confound**, so this machine isolates pure GPU and
|
||||
VRAM effects. That is where DH's quality preset and CTM/texture fidelity live.
|
||||
- **Its CPU is the same class as P2** (both 4C/8T ~4.2 GHz). Comparing this machine against
|
||||
P2 therefore isolates the GPU/VRAM axis while holding CPU-side mod cost roughly constant.
|
||||
That pairing is the fleet's built-in control — see the taxonomy self-check at the end.
|
||||
- **It is the only Windows machine**, so the OS axis is confounded with the GPU axis here.
|
||||
A result that differs from P2 could be the GPU or the driver stack, and this rig cannot
|
||||
separate them. Record it as a known limitation.
|
||||
|
||||
---
|
||||
|
||||
## 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, power plan changed, or GPU throttling → invalid run.
|
||||
|
||||
---
|
||||
|
||||
## Step 1 — Windows power and background load
|
||||
|
||||
```powershell
|
||||
powercfg /list
|
||||
powercfg /setactive SCHEME_MIN # High performance
|
||||
```
|
||||
|
||||
- [ ] Power plan set to **High performance** (or Ultimate Performance) and recorded.
|
||||
- [ ] No pending Windows Update or reboot.
|
||||
- [ ] **Xbox Game Bar off:** Settings → Gaming → Xbox Game Bar → Off.
|
||||
- [ ] **Game DVR / background recording off:** Settings → Gaming → Captures →
|
||||
*Record in the background while I'm playing* → Off. This is a real frametime cost.
|
||||
- [ ] Close browsers, Discord, OneDrive, and any streaming/recording software.
|
||||
- [ ] **Exclude the instance folder from Windows Defender real-time scanning** to remove
|
||||
I/O spikes during chunk loading. Record that you did it.
|
||||
|
||||
## Step 2 — GPU settings
|
||||
|
||||
**NVIDIA Control Panel → Manage 3D settings → Program Settings → (Prism's `javaw.exe`):**
|
||||
|
||||
- [ ] Power management mode → **Prefer maximum performance**
|
||||
- [ ] Vertical sync → **Off**
|
||||
- [ ] Low Latency Mode → fixed value, recorded (it changes frame pacing — don't vary it)
|
||||
- [ ] **Threaded Optimization** → fixed value, recorded (it affects OpenGL apps directly)
|
||||
- [ ] Texture filtering quality → fixed value, recorded
|
||||
|
||||
**Hardware-Accelerated GPU Scheduling (HAGS):** Settings → System → Display → Graphics →
|
||||
*Change default graphics settings*. Record On/Off and **keep it constant**. HAGS changes
|
||||
frame pacing and will show up in your p99 numbers.
|
||||
|
||||
**Fullscreen:** run Minecraft in the **same display mode every session** (fullscreen at
|
||||
native resolution, or borderless — pick one). Also disable *Fullscreen optimizations* for
|
||||
`javaw.exe` (right-click → Properties → Compatibility) so Windows doesn't add compositor
|
||||
work. Record the choice.
|
||||
|
||||
## Step 3 — Confirm GPU state
|
||||
|
||||
`nvidia-smi` ships with the NVIDIA driver on Windows too. **Use the identical command as
|
||||
the Linux machine** so both NVIDIA rigs produce the same CSV schema:
|
||||
|
||||
```powershell
|
||||
& "$env:SystemRoot\System32\nvidia-smi.exe" -q -d PERFORMANCE # check for throttle reasons
|
||||
New-Item -ItemType Directory -Force ~\mcbench\logs | Out-Null
|
||||
& "$env:SystemRoot\System32\nvidia-smi.exe" `
|
||||
--query-gpu=timestamp,memory.used,clocks.sm,clocks.mem,power.draw,temperature.gpu,utilization.gpu `
|
||||
--format=csv -l 1 > ~\mcbench\logs\gpu-$(Get-Date -f yyyy-MM-dd-HHmmss).csv
|
||||
```
|
||||
|
||||
- [ ] No `SW Power Cap` or `HW Slowdown` in the throttle reasons.
|
||||
- [ ] `memory.used` logging running. **On a 6 GB card this is your headline metric** —
|
||||
peak VRAM tells you when DH, CTM and texture fidelity have crossed the line.
|
||||
|
||||
## Step 4 — Measurement tooling: PresentMon
|
||||
|
||||
MangoHud does not exist on Windows. Use **PresentMon** (open source, ETW-based, and it
|
||||
covers OpenGL as well as DX/Vulkan).
|
||||
|
||||
**Option A — the Frame Time Analysis package** (simplest; download from
|
||||
<https://boringboredom.github.io/Frame-Time-Analysis/>). It ships a `Run.bat`:
|
||||
|
||||
```bat
|
||||
pushd %~dp0
|
||||
cd captures
|
||||
..\presentmon.exe --multi_csv --no_console_stats --hotkey "F10"
|
||||
```
|
||||
|
||||
Run it **as Administrator** (ETW capture requires elevation), then press **F10** to
|
||||
start/stop each capture. `--multi_csv` writes a new CSV per capture cycle into `captures/`.
|
||||
|
||||
**Option B — target the Minecraft process explicitly** so only MC is captured:
|
||||
|
||||
```powershell
|
||||
presentmon.exe --process_name javaw.exe --output_file ~\mcbench\logs\pm.csv --timed 30
|
||||
```
|
||||
|
||||
- [ ] Confirm the process name. Prism launches Minecraft as **`javaw.exe`**; verify in Task
|
||||
Manager rather than assuming.
|
||||
- [ ] PresentMon emits **two CSVs per capture**: the raw per-frame data and a **stats
|
||||
summary that already contains average / min / max / percentile FPS**. Use the summary
|
||||
for a quick read and the raw file for the real analysis.
|
||||
- [ ] Verify a capture produces a CSV with a frametime column before collecting real data.
|
||||
|
||||
## Step 5 — Analysis: one tool for the whole fleet
|
||||
|
||||
Use **Frame Time Analysis** (<https://boringboredom.github.io/Frame-Time-Analysis/>). It
|
||||
reads CSV from **PresentMon, CapFrameX, OCAT, MangoHud** and FrameView, all in the browser,
|
||||
with no upload to a third party.
|
||||
|
||||
- [ ] Percentiles, **lows (1% / 0.1%)**, box plots, bar charts and summary tables.
|
||||
- [ ] **Merge multiple CSV files** — this is what lets you put the three runs of one
|
||||
configuration, and the MangoHud CSVs from the Linux machines, side by side on one
|
||||
chart.
|
||||
- [ ] Screenshot export for the record.
|
||||
|
||||
This tool is the reason the fleet does not need a custom analyzer: raw capture stays
|
||||
platform-native (MangoHud on Linux, PresentMon on Windows) and analysis is unified.
|
||||
|
||||
## Step 6 — Launcher and JVM
|
||||
|
||||
Use **Prism Launcher** and launch from a shell so the environment is under your control.
|
||||
|
||||
**Java:** 21 — the **same JVM build as the Linux machines** (Temurin 21 is a good choice for
|
||||
all three). A different JVM build is a confound.
|
||||
|
||||
**JVM arguments** (identical across the fleet except `-Xmx`):
|
||||
|
||||
```
|
||||
-Xmx8G
|
||||
-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
|
||||
```
|
||||
|
||||
32 GB means heap is not a variable here. Keep `-Xmx8G` fixed and spend your attention on
|
||||
VRAM.
|
||||
|
||||
## Step 7 — 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** (also off in the NVIDIA panel — check both)
|
||||
- FOV, resolution, fullscreen mode: fixed and recorded
|
||||
|
||||
## Step 8 — Verification run
|
||||
|
||||
- [ ] PresentMon capture produces a raw CSV **and** a stats summary CSV.
|
||||
- [ ] `nvidia-smi` VRAM logging is producing a CSV.
|
||||
- [ ] MangoHud is not expected here — confirm you are actually capturing through PresentMon.
|
||||
- [ ] Run the same configuration three times and record the spread. Establish this before
|
||||
interpreting anything.
|
||||
- [ ] Confirm peak VRAM is being recorded — it is the whole point of this machine.
|
||||
|
||||
## Step 9 — Per-session checklist
|
||||
|
||||
- [ ] Power plan = High performance
|
||||
- [ ] Game Bar and background recording off
|
||||
- [ ] Defender exclusion in place
|
||||
- [ ] NVIDIA power mode = prefer max performance; vsync off; HAGS and Threaded Optimization
|
||||
unchanged since last session
|
||||
- [ ] `nvidia-smi` throttle check clean
|
||||
- [ ] VRAM logging started
|
||||
- [ ] PresentMon running as Administrator
|
||||
- [ ] Display mode and resolution unchanged
|
||||
- [ ] No pending Windows Update
|
||||
|
||||
## Step 10 — Recording sheet
|
||||
|
||||
| Field | Example |
|
||||
| --- | --- |
|
||||
| Date / session | 2026-09-28-a |
|
||||
| Machine | P1-7700K-1060 |
|
||||
| Config ID | baseline / dh-low / ctm-off / emf-off / … |
|
||||
| Scene | A-base / B-terrain / C-gui |
|
||||
| Run # | 1 / 2 / 3 |
|
||||
| CSV file (raw + summary) | |
|
||||
| p50 / p95 / p99 frametime (ms) | |
|
||||
| 1% low FPS | |
|
||||
| Avg FPS | |
|
||||
| **VRAM peak (MB)** | the headline number for this rig |
|
||||
| Throttle flag | none / SW Power Cap / HW Slowdown |
|
||||
| Notes | |
|
||||
|
||||
---
|
||||
|
||||
## Machine-specific caveats
|
||||
|
||||
- **VRAM is the binding constraint, so watch for the cliff, not the slope.** On a 6 GB card
|
||||
the failure mode is a sharp p99 regression once DH + CTM + texture fidelity exceed
|
||||
capacity — not a smooth FPS decline. Record peak VRAM alongside every result.
|
||||
- **Two vsync switches exist** (in-game and NVIDIA panel). Verify both are off, every
|
||||
session. A single missed vsync makes every configuration look like it hits the target.
|
||||
- **Beware dynamic clocking.** Verify no throttle reasons before and after a block of runs.
|
||||
- **This is the only Windows machine, and it is also the weakest GPU** — the OS axis is
|
||||
confounded with the GPU axis. A divergence from P2 cannot be attributed to the OS.
|
||||
- **32 GB makes this the fleet's clean tier for GPU-only effects.** If a knob you classified
|
||||
as GPU/VRAM shows a large delta here and almost nothing on P2, the taxonomy is confirmed.
|
||||
If a knob you classified as CPU-render diverges between this machine and P2 *in direction*,
|
||||
the classification is wrong — both share the same CPU class, so CPU-side effects should
|
||||
track closely.
|
||||
- **Windows measurement is ETW-based** (PresentMon) while Linux is MangoHud-based. The two
|
||||
do not measure identically, and the fleet has no same-hardware cross-OS pair, so
|
||||
**absolute numbers are not cross-comparable between OSes — only within-OS comparisons
|
||||
are.** Derive ladder orderings per OS, then check that the *orderings* agree.
|
||||
@@ -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.
|
||||
Reference in new issue
Block a user