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.
250 lines
9.7 KiB
Markdown
250 lines
9.7 KiB
Markdown
# 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.
|